|
|
//-----------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1996.
//
// File: utils.c
//
// Contents: Cross Language Migration Tools utility function
//
// History: 09/17/2001 Xiaofeng Zang (xiaoz) Created
//
// Notes:
//
//-----------------------------------------------------------------------
#include "StdAfx.h"
#include "clmt.h"
#include <esent97.h>
#include <dsrole.h>
#include <Ntdsapi.h>
HRESULT MakeDOInfCopy();
//-----------------------------------------------------------------------
//
// Function: ConcatenatePaths
//
// Descrip: Concat the 2 paths into 1 into Target
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: if buffer is small to hold the concated string, return value
// will be false,however, the truncated string still got copied
//
//-----------------------------------------------------------------------
BOOL ConcatenatePaths( LPTSTR Target, LPCTSTR Path, UINT TargetBufferSize )
{ UINT TargetLength,PathLength; BOOL TrailingBackslash,LeadingBackslash; UINT EndingLength;
TargetLength = lstrlen(Target); PathLength = lstrlen(Path);
//
// See whether the target has a trailing backslash.
//
if(TargetLength && (Target[TargetLength-1] == TEXT('\\'))) { TrailingBackslash = TRUE; TargetLength--; } else { TrailingBackslash = FALSE; }
//
// See whether the path has a leading backshash.
//
if(Path[0] == TEXT('\\')) { LeadingBackslash = TRUE; PathLength--; } else { LeadingBackslash = FALSE; }
//
// Calculate the ending length, which is equal to the sum of
// the length of the two strings modulo leading/trailing
// backslashes, plus one path separator, plus a nul.
//
EndingLength = TargetLength + PathLength + 2;
if(!LeadingBackslash && (TargetLength < TargetBufferSize)) { Target[TargetLength++] = TEXT('\\'); }
if(TargetBufferSize > TargetLength) { lstrcpyn(Target+TargetLength,Path,TargetBufferSize-TargetLength); }
//
// Make sure the buffer is nul terminated in all cases.
//
if (TargetBufferSize) { Target[TargetBufferSize-1] = 0; }
return(EndingLength <= TargetBufferSize); }
//-----------------------------------------------------------------------
//
// Function: StrToUInt
//
// Descrip:
//
// Returns: UINT
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
UINT StrToUInt( LPTSTR lpszNum) { LPTSTR lpszStop;
#ifdef UNICODE
return (wcstoul(lpszNum, &lpszStop, 16)); #else
return (strtoul(lpszNum, &lpszStop, 16)); #endif
}
//-----------------------------------------------------------------------
//
// Function: INIFile_ChangeSectionName
//
// Descrip: change a section name in the INF file
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL INIFile_ChangeSectionName( LPCTSTR szIniFileName, LPCTSTR szIniOldSectionName, LPCTSTR szIniNewSectionName) {
LPTSTR pBuf = NULL; BOOL bRetVal = FALSE; DWORD ccbBufsize = 0x7FFFF; DWORD copied_chars;
DPF (INFmsg ,TEXT("[INIFile_ChangeSectionName] Calling ,%s,%s,%s !"), szIniFileName,szIniOldSectionName,szIniNewSectionName); //
// allocate max size of buffer
//
do { if (pBuf) { free(pBuf); ccbBufsize *= 2; } pBuf = (LPTSTR) malloc(ccbBufsize * sizeof(TCHAR)); if (!pBuf) { DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !")); goto Exit1; } copied_chars = GetPrivateProfileSection(szIniOldSectionName, pBuf, ccbBufsize, szIniFileName); } while (copied_chars == ccbBufsize -2);
if (! copied_chars) { //
// this section is not in INI file
//
// do nothing
//
DPF (INFerr,TEXT("[INIFile_ChangeSectionName] No %s section in %s !"),szIniOldSectionName); goto Exit2; } bRetVal = WritePrivateProfileSection( szIniNewSectionName, pBuf, szIniFileName); if (! bRetVal) { //
// write failure
//
DPF (dlError,TEXT("[INIFile_ChangeSectionName] WritePrivateProfileSection fail!")); goto Exit2; } //Delete the old section
WritePrivateProfileSection( szIniOldSectionName, NULL, szIniFileName); //
// at this step, even old section is not deleted, it's still OK
//
bRetVal = TRUE;
Exit2:
if (pBuf) { free(pBuf); }
Exit1: return bRetVal; }
//-----------------------------------------------------------------------
//
// Function: INIFile_ChangeSectionName
//
// Descrip: change a section name in the INF file
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL INIFile_Merge2Section( LPCTSTR szIniFileName, LPCTSTR szSourceSection, LPCTSTR szDestSection) {
LPTSTR pBufSource = NULL, pBufDest = NULL, pBufMerged = NULL; BOOL bRetVal = FALSE; DWORD cchBufsize; DWORD srccopied_chars, dstcopied_chars;
DPF (INFmsg ,TEXT("[INIFile_Merger2Section] Calling ,%s,%s,%s !"), szIniFileName,szSourceSection,szDestSection); //
// allocate max size of buffer
//
cchBufsize = 0x7FFFF; do { if (pBufDest) { free(pBufDest); cchBufsize *= 2; } pBufDest = (LPTSTR) malloc(cchBufsize * sizeof(TCHAR)); if (!pBufDest) { DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !")); goto Exit; } dstcopied_chars = GetPrivateProfileSection(szDestSection, pBufDest, cchBufsize, szIniFileName); } while (dstcopied_chars == cchBufsize -2);
if (! dstcopied_chars) { //
// this section is not in INI file
//
// do nothing
//
DPF (INFerr,TEXT("[INIFile_Merger2Section] No %s section in %s !"),szDestSection); goto Exit; }
cchBufsize = 0x7FFFF; do { if (pBufSource) { free(pBufSource); cchBufsize *= 2; } pBufSource = (LPTSTR) malloc(cchBufsize * sizeof(TCHAR)); if (!pBufSource) { DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !")); goto Exit; } srccopied_chars = GetPrivateProfileSection(szSourceSection, pBufSource, cchBufsize, szIniFileName); } while (srccopied_chars == cchBufsize -2);
if (! srccopied_chars) { //
// this section is not in INI file
//
// do nothing
//
DPF (INFerr,TEXT("[INIFile_Merger2Section] No %s section in %s !"),szSourceSection); goto Exit; } pBufMerged = (LPTSTR) malloc((srccopied_chars + dstcopied_chars + 1) * sizeof(TCHAR)); if (!pBufMerged) { DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !")); goto Exit; } memmove((LPBYTE)pBufMerged,(LPBYTE)pBufDest,dstcopied_chars * sizeof(TCHAR)); memmove((LPBYTE)(pBufMerged + dstcopied_chars),(LPBYTE)pBufSource,srccopied_chars * sizeof(TCHAR)); pBufMerged[srccopied_chars + dstcopied_chars] = TEXT('\0'); bRetVal = WritePrivateProfileSection( szDestSection, pBufMerged, szIniFileName); if (! bRetVal) { //
// write failure
//
DPF (dlError,TEXT("[INIFile_ChangeSectionName] WritePrivateProfileSection fail!")); goto Exit; } bRetVal = TRUE;
Exit: FreePointer(pBufSource); FreePointer(pBufDest); FreePointer(pBufMerged); return bRetVal; }
//-----------------------------------------------------------------------------
//
// Function: INIFile_IsSectionExist
//
// Synopsis: Find out whether the section name is existed in INF file or not
//
// Returns: TRUE if found, FALSE otherwise
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: None.
//
//-----------------------------------------------------------------------------
BOOL INIFile_IsSectionExist( LPCTSTR lpSection, // Section name to be searched
LPCTSTR lpINFFile // INF file name
) { HINF hInf; BOOL fRet = FALSE;
if (NULL == lpSection || NULL == lpINFFile) { return FALSE; }
hInf = SetupOpenInfFile(lpINFFile, NULL, INF_STYLE_WIN4, NULL); if (INVALID_HANDLE_VALUE != hInf) { if (SetupGetLineCount(hInf, lpSection) > 0) { fRet = TRUE; }
SetupCloseInfFile(hInf); }
return fRet; }
//-----------------------------------------------------------------------
//
// Function: IntToString
//
// Descrip:
//
// Returns: void
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
void IntToString( DWORD i, LPTSTR sz) { #define CCH_MAX_DEC 12 // Number of chars needed to hold 2^32
TCHAR szTemp[CCH_MAX_DEC]; int iChr;
iChr = 0;
do { szTemp[iChr++] = TEXT('0') + (TCHAR)(i % 10); i = i / 10; } while (i != 0);
do { iChr--; *sz++ = szTemp[iChr]; } while (iChr != 0);
*sz++ = TEXT('\0'); }
//-----------------------------------------------------------------------
//
// Function: IsDirExisting
//
// Descrip: Check whether the Dir exists or not
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL IsDirExisting(LPTSTR Dir) { LONG lResult = GetFileAttributes(Dir);
DPF (dlInfo,TEXT("[IsDirExisting] %s lResult:%X"),Dir,lResult);
if ((lResult == 0xFFFFFFFF) || (!(lResult & FILE_ATTRIBUTE_DIRECTORY))) { return FALSE; } else { return TRUE; } }
LONG IsDirExisting2(LPTSTR Dir, PBOOL pbExit) { LONG lResult = GetFileAttributes(Dir);
DPF (dlInfo,TEXT("[IsDirExisting] %s lResult:%X"),Dir,lResult);
if (lResult == INVALID_FILE_ATTRIBUTES) { DWORD dwErr = GetLastError(); if ( (dwErr == ERROR_FILE_NOT_FOUND) || (dwErr == ERROR_PATH_NOT_FOUND) ) { *pbExit = FALSE; return ERROR_SUCCESS; } else { return dwErr; } } else { *pbExit = TRUE; return ERROR_SUCCESS; } }
//-----------------------------------------------------------------------
//
// Function: IsFileFolderExisting
//
// Descrip: Check whether the File exists or not
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
BOOL IsFileFolderExisting( LPTSTR File) { LONG lResult = GetFileAttributes(File);
DPF (dlInfo,TEXT("[IsFileFolderExisting] %s lResult:%X"),File,lResult);
if (lResult == 0xFFFFFFFF) { return FALSE; } else { return TRUE; } }
//-----------------------------------------------------------------------
//
// Function: MyMoveFile
//
// Descrip: Rename a file or direcory
//
// Returns: HRESULT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
HRESULT MyMoveFile( LPCTSTR lpExistingFileName, // file name
LPCTSTR lpNewFileName, // new file name
BOOL bAnalyze, // if it's analyze mode, it will add an entry in INF file
// for future renaming
BOOL bIsFileProtected) { LPCTSTR lpMyNewFileName = lpNewFileName;
if (!lpExistingFileName) { return E_INVALIDARG; } if (!IsFileFolderExisting((LPTSTR)lpExistingFileName)) { return S_FALSE; } if (!MyStrCmpI(lpExistingFileName,lpNewFileName)) { return S_FALSE; }
if (!lpNewFileName || !lpNewFileName[0]) { lpMyNewFileName = NULL; } if (bAnalyze) { HRESULT hr; DWORD dwType;
if (bIsFileProtected) { dwType = TYPE_SFPFILE_MOVE; } else { dwType = TYPE_FILE_MOVE; } return (AddFolderRename((LPTSTR)lpExistingFileName,(LPTSTR)lpMyNewFileName,dwType,NULL)); } else { if (MoveFileEx(lpExistingFileName,lpMyNewFileName,MOVEFILE_DELAY_UNTIL_REBOOT)) { return S_OK; } else { return HRESULT_FROM_WIN32(GetLastError()); } } }
//-----------------------------------------------------------------------
//
// Function: AddHardLinkEntry
//
// Descrip: add an entry in hardlink section
//
// Returns: HRESULT
//
// Notes:
//
// History: 04/10/2002 xiaoz created
//
// Notes: none
//
//-----------------------------------------------------------------------
HRESULT AddHardLinkEntry( LPTSTR szLinkName, //Link Name to created
LPTSTR szLinkValue, //the name you want to link to
LPTSTR szType, LPTSTR lpUser, LPTSTR lpHiddenType, LPTSTR lpKeyname ) { LPTSTR lpszSectionName; LPTSTR szOneLine = NULL; size_t CchOneLine = MAX_PATH; TCHAR szIndex[MAX_PATH]; LPTSTR lpCurrIndex = szIndex; HRESULT hr;
if (!szLinkName ||!szLinkValue || !szType || !szLinkName[0] || !szLinkValue[0] || !szType[0]) { hr = E_INVALIDARG; goto Cleanup; } CchOneLine += lstrlen(szLinkName)+lstrlen(szLinkValue) +lstrlen(szType); szOneLine = malloc(CchOneLine * sizeof(TCHAR)); if (!szOneLine) { hr = E_OUTOFMEMORY; goto Cleanup; } if (!lpHiddenType) { hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%s,\"%s\",\"%s\""), szType,szLinkName,szLinkValue); } else { hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%s,\"%s\",\"%s\",\"%s\""), szType,szLinkName,szLinkValue,lpHiddenType); } if (FAILED(hr)) { goto Cleanup; } if (lpKeyname && (g_dwKeyIndex < 0xFFFF)) { g_dwKeyIndex = 0xFFFF; _itot(g_dwKeyIndex,szIndex,16); } else { g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); }
if (lpUser && !MyStrCmpI(lpUser,DEFAULT_USER)) { lpszSectionName = TEXT("Folder.HardLink.Peruser"); } else { lpszSectionName = TEXT("Folder.HardLink"); } if (!WritePrivateProfileString(lpszSectionName,lpCurrIndex,szOneLine,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } hr = S_OK; Cleanup: if (szOneLine) { free(szOneLine); } return hr; }
//-----------------------------------------------------------------------
//
// Function: MyMoveDirectory
//
// Descrip: Rename SourceDir to DestDir
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: if the directory is in use, a deferred move will be
// performed and we set the system reboot statue
// MoveFileEx will fail for directory when DestDir is
// already exitsing
// if bTakeCareBackupDir is TRUE, this function will make
// a backup for DestDir if it exists.
//-----------------------------------------------------------------------
HRESULT MyMoveDirectory( LPTSTR SourceDir, LPTSTR DestDir, BOOL bTakeCareBackupDir, BOOL bAnalyze, BOOL bCreateHardLink, DWORD dwShellID) { HRESULT hr; size_t cChSourceDir, cChDestDir ; LPTSTR lpSourceBackupDir, lpDestBackupDir; BOOL bDirExist; DWORD dwStatus; lpSourceBackupDir = lpDestBackupDir = NULL;
dwStatus = IsDirExisting2(SourceDir,&bDirExist); if (ERROR_SUCCESS == dwStatus) { if (!bDirExist) { hr = S_FALSE; goto Cleanup; } } else { hr = HRESULT_FROM_WIN32(dwStatus); DPF(APPerr, TEXT("Error: current user maybe can not access folder %s "),SourceDir); goto Cleanup; }
if (!MyStrCmpI(SourceDir,DestDir)) { hr = S_FALSE; goto Cleanup; }
if (bAnalyze) { BOOL bAccess; LPTSTR lp = StrRChrI(SourceDir,NULL,TEXT('\\')); TCHAR cCh; if (!lp) { hr = S_FALSE; goto Cleanup; } //Try self first
hr = IsObjectAccessiablebyLocalSys(SourceDir,SE_FILE_OBJECT,&bAccess); if (hr != S_OK) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir); goto Cleanup; }
//try parent
if (*(lp-1) == TEXT(':')) { lp++; } cCh = *lp; *lp = TEXT('\0'); hr = IsObjectAccessiablebyLocalSys(SourceDir,SE_FILE_OBJECT,&bAccess); if (hr != S_OK) { hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir); goto Cleanup; } if (!bAccess) { DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir); hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); goto Cleanup; } *lp = cCh; if (bTakeCareBackupDir && IsDirExisting(DestDir)) { LPTSTR lpOld,lpNew,lpLastSlash; //
// RERKBOOS: Add more code here...
// We merge the content from Backup English folder to localized folder
// then we will rename localized folder to English folder
//
#ifdef NEVER
//Testing team decides to change mind and better not to add this code
//we will just follow here
hr = MergeDirectory(DestDir, SourceDir); if (FAILED(hr)) { goto Cleanup; } #endif
//We need to make sure DestDir does not exist
cChDestDir = lstrlen(DestDir)+ MAX_PATH; lpDestBackupDir = malloc(cChDestDir * sizeof(TCHAR)); if (!lpDestBackupDir) { hr = E_OUTOFMEMORY; goto Cleanup; } if (!GetBackupDir( DestDir,lpDestBackupDir,cChDestDir,FALSE)) { hr = E_FAIL; goto Cleanup; } if (FAILED(hr = AddFolderRename(DestDir,lpDestBackupDir,TYPE_DIR_MOVE,NULL))) { goto Cleanup; } lpOld = StrRChrI(DestDir,NULL,TEXT('\\')); lpNew = StrRChrI(lpDestBackupDir,NULL,TEXT('\\')); lpLastSlash = lpOld; if (lpOld && lpNew) { lpOld++; lpNew++; //*lpLastSlash = TEXT('\0');
if (!AddItemToStrRepaceTable(TEXT("SYSTEM"),lpOld,lpNew,DestDir, dwShellID,&g_StrReplaceTable)) { hr = E_OUTOFMEMORY; goto Cleanup; } //*lpLastSlash = TEXT('\\');
}
} else { //We need to make sure DestDir does not exist
cChDestDir = lstrlen(DestDir)+ MAX_PATH; lpDestBackupDir = malloc(cChDestDir * sizeof(TCHAR)); if (lpDestBackupDir) { if (GetBackupDir( DestDir,lpDestBackupDir,cChDestDir,FALSE)) { AddFolderRename(DestDir,lpDestBackupDir,TYPE_DIR_MOVE,NULL); } } } } //if we are here we are safe to move source dir to destination
if (bAnalyze) { if (FAILED(hr = AddFolderRename(SourceDir,DestDir,TYPE_DIR_MOVE,NULL))) { goto Cleanup; } /*if (bCreateHardLink)
{ if (FAILED(hr = AddHardLinkEntry(SourceDir,DestDir))) { goto Cleanup; } }*/ } else { if (!MoveFileEx(SourceDir,DestDir,MOVEFILE_DELAY_UNTIL_REBOOT)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } }
if (bAnalyze && bTakeCareBackupDir) { cChSourceDir = lstrlen(SourceDir)+ MAX_PATH; lpSourceBackupDir = malloc(cChSourceDir * sizeof(TCHAR)); if (!lpSourceBackupDir) { hr = E_OUTOFMEMORY; goto Cleanup; } if (GetBackupDir( SourceDir,lpSourceBackupDir,cChSourceDir,TRUE)) { LPTSTR lpOld,lpNew,lpLastSlash;
if (FAILED(hr = AddFolderRename(lpSourceBackupDir,SourceDir,TYPE_DIR_MOVE,NULL))) { goto Cleanup; } lpOld = StrRChrI(lpSourceBackupDir,NULL,TEXT('\\')); lpNew = StrRChrI(SourceDir,NULL,TEXT('\\')); lpLastSlash = lpOld; if (lpOld && lpNew) { lpOld++; lpNew++; //*lpLastSlash = TEXT('\0');
if (!AddItemToStrRepaceTable(TEXT("SYSTEM"),lpOld,lpNew,lpSourceBackupDir, dwShellID,&g_StrReplaceTable)) { hr = E_OUTOFMEMORY; goto Cleanup; } //*lpLastSlash = TEXT('\\');
}
} } hr = S_OK; Cleanup: FreePointer(lpSourceBackupDir); FreePointer(lpDestBackupDir); return hr; }
//-----------------------------------------------------------------------
//
// Function: UpdateINFFileSys
//
// Descrip: adding ALLUSERSPROFILE/HOMEDRIVE/WINDIR Key in [String] section
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
// 03/05/2002 rerkboos modified
//
// Notes:
//
//-----------------------------------------------------------------------
HRESULT UpdateINFFileSys( LPTSTR lpInfFile ) { HRESULT hr = E_FAIL; DWORD dwSize; TCHAR szStringSection[32]; TCHAR szProfileDir[MAX_PATH]; TCHAR szWindir[MAX_PATH+1]; TCHAR szHomeDrive[MAX_PATH]; TCHAR szSystemDrive[MAX_PATH]; TCHAR szStr[MAX_PATH]; TCHAR szComputerName[16]; TCHAR szBackupDir[MAX_PATH]; TCHAR szFirstNTFSDrive[4]; INT i;
struct _EnvPair { LPCTSTR lpEnvVarName; LPCTSTR lpValue; };
struct _EnvPair epCLMT[] = { TEXT("ALLUSERSPROFILE"), szProfileDir, TEXT("HOMEDRIVE"), szHomeDrive, TEXT("WINDIR"), szWindir, TEXT("SYSTEMDRIVE"), szSystemDrive, TEXT("COMPUTERNAME"), szComputerName, TEXT("MUIBACKUPDIR"), szBackupDir, TEXT("FIRSTNTFSDRIVE"), szFirstNTFSDrive, NULL, NULL };
if (lpInfFile == NULL) { return E_INVALIDARG; }
DPF(APPmsg, TEXT("Enter UpdateINFFileSys:"));
//
// Get neccessary environment variables from system
//
dwSize = ARRAYSIZE(szProfileDir); if (!GetAllUsersProfileDirectory(szProfileDir, &dwSize)) { DPF(APPerr, TEXT("Failed to get ALLUSERPROFILE")); hr = HRESULT_FROM_WIN32(GetLastError()); goto EXIT; }
dwSize = ARRAYSIZE(szComputerName); if (!GetComputerName(szComputerName, &dwSize)) { DPF(APPerr, TEXT("Failed to get computer name")); hr = HRESULT_FROM_WIN32(GetLastError()); goto EXIT; }
if (!GetSystemWindowsDirectory(szWindir, ARRAYSIZE(szWindir))) { DPF(APPerr, TEXT("Failed to get WINDIR")); hr = HRESULT_FROM_WIN32(GetLastError()); goto EXIT; }
if (!GetEnvironmentVariable(TEXT("HOMEDRIVE"), szHomeDrive, ARRAYSIZE(szHomeDrive))) { DWORD dw = GetLastError(); DPF(APPerr, TEXT("Failed to get HOMEDRIVE")); hr = HRESULT_FROM_WIN32(GetLastError()); goto EXIT; }
if (!GetEnvironmentVariable(TEXT("SystemDrive"), szSystemDrive, ARRAYSIZE(szSystemDrive))) { DPF(APPerr, TEXT("Failed to get SystemDrive")); hr = HRESULT_FROM_WIN32(GetLastError()); goto EXIT; }
hr = StringCchCopy(szBackupDir, ARRAYSIZE(szBackupDir), szWindir); if (SUCCEEDED(hr)) { ConcatenatePaths(szBackupDir, CLMT_BACKUP_DIR, ARRAYSIZE(szBackupDir)); if (!CreateDirectory(szBackupDir, NULL)) { hr = HRESULT_FROM_WIN32(GetLastError()); if (HRESULT_CODE(hr) != ERROR_ALREADY_EXISTS) { goto EXIT; } } } else { goto EXIT; }
hr = GetFirstNTFSDrive(szFirstNTFSDrive, ARRAYSIZE(szFirstNTFSDrive)); if (FAILED(hr)) { DPF(APPerr, TEXT("Failed to get first NTFS drive in system")); goto EXIT; }
//
// Generate strings section depend on operation mode
//
hr = InfGenerateStringsSection(lpInfFile, szStringSection, ARRAYSIZE(szStringSection)); if (FAILED(hr)) { DPF(APPerr, TEXT("InfGenerateStringsSection failed")); goto EXIT; }
//
// Update private environment variables to INF file
//
for (i = 0 ; epCLMT[i].lpEnvVarName != NULL ; i++) { hr = StringCchPrintf(szStr, ARRAYSIZE(szStr), TEXT("\"%s\""), epCLMT[i].lpValue); if (SUCCEEDED(hr)) { BOOL bRet; bRet = WritePrivateProfileString(szStringSection, epCLMT[i].lpEnvVarName, szStr, lpInfFile); if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(APPerr, TEXT("Failed to append private variable to INF file")); break; } } else { DPF(APPerr, TEXT("StringCchPrintf failed")); break; } }
EXIT:
DPF(APPmsg, TEXT("Exit UpdateINFFileSys:"));
return hr; }
//-----------------------------------------------------------------------
//
// Function: InfGenerateStringsSection
//
// Descrip: Generate [Strings] section from localized and English
// sections. If the operation is normal source strings are
// from localized section and destination strings are from
// English section. vice versa if the operation is Undo.
//
// Returns: HRESULT
//
// Notes:
//
// History: 03/05/2002 rerkboos Created
//
// Notes: none.
//
//-----------------------------------------------------------------------
HRESULT InfGenerateStringsSection( LPCTSTR lpInfFile, // INF file name
LPTSTR lpFinalSection, // Output section name that stores required strings
SIZE_T cchFinalSection // Size of lpFinalSection in TCHAR
) { LPVOID lpBuffer; LPVOID lpOldBuffer; LPCTSTR lpSection; LPCTSTR lpSrcSection; LPCTSTR lpDstSection; DWORD cbBuffer; DWORD cchRead; TCHAR szLocSection[16]; BOOL bRet = TRUE; HRESULT hr = S_OK; LCID lcidOriginal;
const TCHAR szFinalSection[] = TEXT("Strings"); const TCHAR szEngSection[] = TEXT("Strings.0409"); const TCHAR szPrefixSRC[] = TEXT("SRC_"); const TCHAR szPrefixDST[] = TEXT("DST_");
if (lpInfFile == NULL || lpFinalSection == NULL) { return E_INVALIDARG; }
hr = GetSavedInstallLocale(&lcidOriginal); if (SUCCEEDED(hr)) { hr = StringCchPrintf(szLocSection, ARRAYSIZE(szLocSection), TEXT("Strings.%04X"), lcidOriginal); } if (FAILED(hr)) { return hr; } if (MyStrCmpI(szLocSection,szEngSection) == LSTR_EQUAL) { return E_NOTIMPL; }
cbBuffer = 8192; lpBuffer = MEMALLOC(cbBuffer); if (lpBuffer == NULL) { return E_OUTOFMEMORY; }
cchRead = GetPrivateProfileSectionNames(lpBuffer, cbBuffer / sizeof(TCHAR), lpInfFile); while (cchRead == (cbBuffer / sizeof(TCHAR)) - 2) { // Buffer is too small, reallocate until we have enough
lpOldBuffer = lpBuffer; cbBuffer += 8192;
lpBuffer = MEMREALLOC(lpOldBuffer, cbBuffer); if (lpBuffer == NULL) { MEMFREE(lpOldBuffer); return E_OUTOFMEMORY; }
// Read the data from section again
cchRead = GetPrivateProfileSectionNames(lpBuffer, cbBuffer / sizeof(TCHAR), lpInfFile); }
// At this point we have big enough buffer and data in it
if (cchRead > 0) { lpSection = MultiSzTok(lpBuffer); while (lpSection != NULL) { if (StrStrI(lpSection, TEXT("Strings.")) != NULL) { // This is one of Strings sections,
// Delete all sections that do not match current locale and English
if (MyStrCmpI(lpSection, szLocSection) != LSTR_EQUAL && MyStrCmpI(lpSection, szEngSection) != LSTR_EQUAL) { bRet = WritePrivateProfileSection(lpSection, NULL, lpInfFile); if (!bRet) { break; } } }
// Get next section name
lpSection = MultiSzTok(NULL); }
// no error occured
bRet = TRUE; } else { SetLastError(ERROR_NOT_FOUND); bRet = FALSE; }
MEMFREE(lpBuffer);
if (!bRet) { return HRESULT_FROM_WIN32(GetLastError()); }
//
// Merge strings from Loc and Eng section to [Strings] section
//
if (g_dwRunningStatus != CLMT_UNDO_PROGRAM_FILES && g_dwRunningStatus != CLMT_UNDO_APPLICATION_DATA && g_dwRunningStatus != CLMT_UNDO_ALL) { lpSrcSection = szLocSection; lpDstSection = szEngSection; } else { lpSrcSection = szEngSection; lpDstSection = szLocSection; }
// Copy source strings to [Strings] section with SRC_ prefix
hr = InfCopySectionWithPrefix(lpSrcSection, szFinalSection, szPrefixSRC, lpInfFile); if (SUCCEEDED(hr)) { // Copy destination strings to [Strings] section with DSTs_ prefix
hr = InfCopySectionWithPrefix(lpDstSection, szFinalSection, szPrefixDST, lpInfFile); if (SUCCEEDED(hr)) { WritePrivateProfileSection(lpSrcSection, NULL, lpInfFile); WritePrivateProfileSection(lpDstSection, NULL, lpInfFile); hr = StringCchCopy(lpFinalSection, cchFinalSection, szFinalSection); } }
return hr; }
//-----------------------------------------------------------------------
//
// Function: InfCopySectionWithPrefix
//
// Descrip: Copy keys from source section to destination and append
// prefix to key name in destination section
//
// Returns: HRESULT
//
// Notes:
//
// History: 03/05/2002 rerkboos Created
//
// Notes: none.
//
//-----------------------------------------------------------------------
HRESULT InfCopySectionWithPrefix( LPCTSTR lpSrcSection, // Source section name
LPCTSTR lpDstSection, // Destination section name
LPCTSTR lpPrefix, // Prefix to add to key name
LPCTSTR lpInfFile // Inf file name
) { HRESULT hr = E_NOTIMPL; BOOL bRet; LPVOID lpBuffer; LPVOID lpOldBuffer; DWORD cbBuffer; DWORD cchRead; LPTSTR lpSz; LPTSTR lpKey; LPTSTR lpValue; TCHAR szPrefixedKey[MAX_PATH];
if (lpSrcSection == NULL || lpDstSection == NULL || lpInfFile == NULL) { return E_INVALIDARG; }
//
// Read data from source section into memory
//
cbBuffer = 65536; lpBuffer = MEMALLOC(cbBuffer); if (lpBuffer == NULL) { return E_OUTOFMEMORY; }
cchRead = GetPrivateProfileSection(lpSrcSection, lpBuffer, cbBuffer / sizeof(TCHAR), lpInfFile); while (cchRead == (cbBuffer / sizeof(TCHAR)) - 2) { // Buffer is too small, reallocate until we have enough
lpOldBuffer = lpBuffer; cbBuffer += 65536; lpBuffer = MEMREALLOC(lpOldBuffer, cbBuffer); if (lpBuffer == NULL) { MEMFREE(lpOldBuffer); return E_OUTOFMEMORY; }
// Read the data from section again
cchRead = GetPrivateProfileSection(lpSrcSection, lpBuffer, cbBuffer / sizeof(TCHAR), lpInfFile);
}
//
// Write key with prefix to destination section
//
lpKey = (LPTSTR) MultiSzTok((LPCTSTR) lpBuffer); while (lpKey != NULL) { lpValue = StrStr(lpKey, TEXT("=")); *lpValue = TEXT('\0');
hr = StringCchPrintf(szPrefixedKey, ARRAYSIZE(szPrefixedKey), TEXT("%s%s"), lpPrefix, lpKey); if (FAILED(hr)) { break; }
*lpValue = TEXT('='); lpValue++;
bRet = WritePrivateProfileString(lpDstSection, szPrefixedKey, lpValue, lpInfFile); if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); break; }
// Get next Sz value
lpKey = (LPTSTR) MultiSzTok(NULL); }
MEMFREE(lpBuffer); return hr; }
//-----------------------------------------------------------------------
//
// Function: UpdateINFFilePerUser
//
// Descrip: adding user specific key name in [Strings] section
//
// Returns: HRESULT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
// 03/08/2002 rerkboos modified to work with SRC/DST format
//
// Notes:
//
//-----------------------------------------------------------------------
HRESULT UpdateINFFilePerUser( LPCTSTR lpInfFile, LPCTSTR lpUserName, LPCTSTR lpUserSid, BOOL bCureMode ) { HRESULT hr = S_OK; BOOL bRet = FALSE; DWORD dwSize; TCHAR szExpandedUserProfilePath[MAX_PATH]; TCHAR szStr[MAX_PATH + 2]; UINT uInstLocale; TCHAR szRegKey[MAX_PATH]; HRESULT hRes; LONG lRet; DWORD cbStr; const TCHAR szStringsSection[] = TEXT("Strings");
if (lpInfFile == NULL || lpUserName == NULL) { hr = E_INVALIDARG; goto Cleanup; }
DPF(APPmsg, TEXT("Enter UpdateINFFilePerUser"));
dwSize = MAX_PATH; if (GetDefaultUserProfileDirectory(szExpandedUserProfilePath, &dwSize)) { if (MyStrCmpI(DEFAULT_USER, lpUserName)) { hr = StringCchCopy(szRegKey, ARRAYSIZE(szRegKey), g_cszProfileList); if (SUCCEEDED(hr)) { hr = StringCchCat(szRegKey, ARRAYSIZE(szRegKey), TEXT("\\")); hr = StringCchCat(szRegKey, ARRAYSIZE(szRegKey), lpUserSid); if (SUCCEEDED(hr)) { cbStr = sizeof(szStr); lRet = GetRegistryValue(HKEY_LOCAL_MACHINE, szRegKey, g_cszProfileImagePath, (LPBYTE) szStr, &cbStr); if (lRet == ERROR_SUCCESS) { ExpandEnvironmentStrings(szStr, szExpandedUserProfilePath, ARRAYSIZE(szExpandedUserProfilePath)); } else { hr = E_FAIL; } } }
if (FAILED(hr)) { DPF(APPerr, TEXT("Failed to get profile directory for user")); } }
if (SUCCEEDED(hr)) { hr = StringCchPrintf(szStr, ARRAYSIZE(szStr), TEXT("\"%s\""), szExpandedUserProfilePath); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(APPerr, TEXT("Failed to get default user profile directory")); goto Cleanup; } if (SUCCEEDED(hr)) { if (bCureMode) { if (!WritePrivateProfileString(szStringsSection, lpUserSid, szStr, lpInfFile)) { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(APPerr, TEXT("Failed to write environment variable")); }
} else { if (!WritePrivateProfileString(szStringsSection, TEXT("USERPROFILE"), szStr, lpInfFile)) { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(APPerr, TEXT("Failed to write environment variable")); } } }
if (!bCureMode) { if (!WritePrivateProfileString(szStringsSection, TEXT("USER_SID"), lpUserSid, lpInfFile)) { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(APPerr, TEXT("Failed to write environment variable")); goto Cleanup; } }
hr = S_OK; DPF(APPmsg, TEXT("Exit UpdateINFFilePerUser")); Cleanup: return hr; }
//-----------------------------------------------------------------------
//
// Function: GetInfFilePath
//
// Descrip: Get a file name for temp INF file
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
// 03/06/2002 rerkboos Read INF from resource
//
// Notes:
//
//-----------------------------------------------------------------------
HRESULT GetInfFilePath( LPTSTR lpInfFile, // Output buffer store INF file name
SIZE_T cchInfFile // Len of buffer in TCHAR
) { HRESULT hr = S_OK; BOOL bRet = FALSE; TCHAR *p; TCHAR szSysDir[MAX_PATH]; TCHAR szInfSource[MAX_PATH]; TCHAR szTempName[MAX_PATH]; LPTSTR lpFileName; if (!lpInfFile) { return E_INVALIDARG; }
DPF(dlPrint, TEXT("Enter GetInfFilePath:"));
// Contruct a tmp file name for our INF in szSysDir
// The temp INF file is in %windir%\system32\clmt*.tmp
if (GetSystemDirectory(szSysDir, ARRAYSIZE(szSysDir))) { if (GetTempFileName(szSysDir, TEXT("clmt"), 0, szTempName)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(dlError, TEXT("Failed to get temp file name")); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(dlError, TEXT("Failed to get system directory")); } if (SUCCEEDED(hr)) { // We will use template from inf file if user supply /INF switch
// otherwise we will grab it from resource section
if (g_fUseInf) { //
// Use user-supply INF as template
//
if (GetFullPathName(g_szInfFile, ARRAYSIZE(szInfSource), szInfSource, &lpFileName)) { // Copy the source INF file to %windir%\system32\clmt*.tmp
if (CopyFile(szInfSource, szTempName, FALSE)) { DPF(dlPrint, TEXT("Use inf from %s"), g_szInfFile); hr = StringCchCopy(lpInfFile, cchInfFile, szTempName); } else { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(dlError, TEXT("Failed to copy temporary INF file")); } } else { hr = HRESULT_FROM_WIN32(GetLastError()); DPF(dlError, TEXT("%s not found."), g_szInfFile); } } else { //
// Use template from resource
//
DPF(dlPrint, TEXT("Use INF from resource"));
hr = GetInfFromResource(szTempName); if (SUCCEEDED(hr)) { hr = StringCchCopy(g_szInfFile, ARRAYSIZE(g_szInfFile), szTempName); hr = StringCchCopy(lpInfFile, cchInfFile, szTempName); } else { DPF(dlError, TEXT("Failed to read INF file from resource")); } } }
DPF(dlPrint, TEXT("Exit GetInfFilePath:"));
return hr; }
//-----------------------------------------------------------------------
//
// Function: GetInfFromResource
//
// Descrip: Read INF file from resource section and write it to output
// file.
//
// Returns: HRESULT
//
// Notes:
//
// History: 03/08/2002 rerkboos Created
//
// Notes:
//
//-----------------------------------------------------------------------
HRESULT GetInfFromResource( LPCTSTR lpDstFile // Output file name
) { HRESULT hr = E_FAIL; HMODULE hExe; BOOL bRet = FALSE;
if (lpDstFile == NULL) { return E_INVALIDARG; }
// Get the handle to our executable
hExe = GetModuleHandle(NULL); if (hExe) { // Inf is stored in RCDATA type with the name "CLMTINF"
HRSRC hRsrc = FindResource(hExe, TEXT("CLMTINF"), RT_RCDATA); if (hRsrc) { DWORD cbBuffer; LPVOID lpBuffer;
cbBuffer = SizeofResource(hExe, hRsrc); if (cbBuffer > 0) { lpBuffer = MEMALLOC(cbBuffer); if (lpBuffer) { HGLOBAL hGlobal = LoadResource(hExe, hRsrc); if (hGlobal) { LPVOID lpLockGlobal = LockResource(hGlobal); if (lpLockGlobal) { HANDLE hFile;
CopyMemory(lpBuffer, lpLockGlobal, cbBuffer); hFile = CreateFile(lpDstFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); if (hFile != INVALID_HANDLE_VALUE) { DWORD cbWritten;
bRet = WriteFile(hFile, lpBuffer, cbBuffer, &cbWritten, NULL); CloseHandle(hFile); } } }
MEMFREE(lpBuffer); } else { SetLastError(ERROR_OUTOFMEMORY); } } } }
if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { hr = S_OK; }
return hr; }
//*************************************************************
// ReplaceString
//
// Purpose: Replace a string
//
// Parameter: lpszOldStr: Orignal string
// lpszReplaceStr: Search string
// lpszReplacedWithStr: String to be replaced with
// lpszOutputStr: Output buffer
// cbszOutputStr: size of output buffer
// lpszTailCheck: point to predefined tail character
// lpSysPath: point to standard system path
// lpAttrib: point to string attribute
// bStrCheck: True -- do it, or False -- skip it
//
// History: 12/10/2001 geoffguo created
//
// Note: Tail check is right side check.
// For example, "Documents" and "Documents and Settings". if you search
// "Documents", to avoid mismatch, we check the next character of "Documents".
//*************************************************************
BOOL ReplaceString( LPCTSTR lpszOldStr, LPCTSTR lpszReplaceStr, LPCTSTR lpszReplacedWithStr, LPTSTR lpszOutputStr, size_t cbszOutputStr, LPCTSTR lpszTailCheck, LPCTSTR lpSysPath, LPDWORD lpAttrib, BOOL bStrCheck) { BOOL bRet = FALSE; DWORD dwLen, dwStrNum; LPTSTR pszAnchor = NULL; TCHAR cTemp; TCHAR *p;
if (!lpszOldStr || !lpszReplaceStr || !lpszReplacedWithStr || !lpszOutputStr) { return bRet; }
dwStrNum = 0; dwLen = lstrlen(lpszReplaceStr); p = (LPTSTR)lpszOldStr; lpszOutputStr[0] = TEXT('\0');
while (*p) { //get the first occurance of the string needs to be replaced
pszAnchor = StrStrI(p,lpszReplaceStr);
if (pszAnchor) { dwStrNum++; if (!bStrCheck || StringValidationCheck(lpszOldStr, lpszReplaceStr, lpSysPath, lpszTailCheck, lpAttrib, dwStrNum)) { cTemp = *pszAnchor; *pszAnchor = L'\0'; if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p))) { bRet = FALSE; goto Exit; } if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,lpszReplacedWithStr))) { bRet = FALSE; goto Exit; } *pszAnchor = cTemp; bRet = TRUE; } else //Copy invalid matching string
{ cTemp = *(pszAnchor+dwLen); *(pszAnchor+dwLen) = L'\0'; if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p))) { bRet = FALSE; goto Exit; } *(pszAnchor+dwLen) = cTemp; } p = pszAnchor+dwLen; } else //Copy string
{ if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p))) { bRet = FALSE; goto Exit; } break; } }
Exit: return bRet; }
//-----------------------------------------------------------------------
//
// Function: StringMultipleReplacement
//
// Descrip: string replacement with multiple replace pair
//
// Returns: HRESULT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
// lpszOldStr : The source string
// lpszReplaceMSzStr : multi string instance that needs to be replaced
// lpszReplacedWithMSzStr : multi string instance that will replace to
// lpszOutputStr: output buffer
// cbszOutputStr:buffer size for lpszOutputStr
//
//-----------------------------------------------------------------------
HRESULT StringMultipleReplacement( LPCTSTR lpszOldStr, LPCTSTR lpszReplaceMSzStr, LPCTSTR lpszReplacedWithMSzStr, LPTSTR lpszOutputStr, size_t cchOutputStr) { HRESULT hr; DWORD dwLen; LPTSTR pszAnchor = NULL; TCHAR cTemp; LPTSTR pOld,pNew; LPTSTR pTmp = NULL; TCHAR cNonChar = TEXT('\xFFFF');
if (!lpszOldStr || !lpszReplaceMSzStr || !lpszReplacedWithMSzStr || !lpszOutputStr) { hr = E_INVALIDARG; goto Cleanup; }
pOld = (LPTSTR)lpszReplaceMSzStr; pNew = (LPTSTR)lpszReplacedWithMSzStr;
//alloc temp buffer for intermediate string
pTmp = malloc(cchOutputStr*sizeof(TCHAR)); if (!pTmp) { hr = E_OUTOFMEMORY; goto Cleanup; } if (FAILED(hr = StringCchCopy(pTmp,cchOutputStr,lpszOldStr))) { goto Cleanup; } while (*pOld && *pNew) { if (!ReplaceString(pTmp,pOld,pNew,lpszOutputStr, cchOutputStr,&cNonChar, NULL, NULL, TRUE)) { hr = E_OUTOFMEMORY; goto Cleanup; } pOld += (lstrlen(pOld) + 1); pNew += (lstrlen(pNew) + 1); if (FAILED(hr = StringCchCopy(pTmp,cchOutputStr,lpszOutputStr))) { goto Cleanup; } } hr = S_OK; Cleanup: FreePointer(pTmp); return hr; }
//-----------------------------------------------------------------------
//
// Function: MultiSzSubStr
//
// Descrip: multiSZ version of substr
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: return TRUE is szString is a sub string of a string in szMultiSz
//
//-----------------------------------------------------------------------
BOOL MultiSzSubStr ( LPTSTR szString, LPTSTR szMultiSz) { TCHAR *p = szMultiSz; while (*p) { if (StrStrI(p,szString)) { return TRUE; } p += (lstrlen(p) + 1); } return FALSE; }
//-----------------------------------------------------------------------
//
// Function: IsStrInMultiSz
//
// Descrip: check whether is string is in MultiSz
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
//
//-----------------------------------------------------------------------
BOOL IsStrInMultiSz ( LPCTSTR szString, LPCTSTR szMultiSz) { LPCTSTR p = szMultiSz; while (*p) { if (!MyStrCmpI(p,szString)) { return TRUE; } p += (lstrlen(p) + 1); } return FALSE; }
//-----------------------------------------------------------------------
//
// Function: MultiSzLen
//
// Descrip: Returns the length (in characters) of the buffer required to hold a multisz,
// INCLUDING the trailing null.
//
// Returns: DWORD
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
// Example: MultiSzLen("foo\0bar\0") returns 9
//
//-----------------------------------------------------------------------
DWORD MultiSzLen(LPCTSTR szMultiSz) { TCHAR *p = (LPTSTR) szMultiSz; DWORD dwLen = 0;
if (!p) { return 0; } if (!*p) { return 2; } while (*p) { dwLen += (lstrlen(p) +1); p += (lstrlen(p) + 1); } // add one for the trailing null character
return (dwLen+1); }
//-----------------------------------------------------------------------
//
// Function: MultiSzTok
//
// Descrip: Extract an sz string from multisz string
// (work similar to strtok, but use '\0' as seperator)
//
// Returns: Pointer to next Sz string
// NULL if no string left
//
// Notes:
//
// History: 03/05/2002 rerkboos Created
//
// Notes: Supply the pointer to multisz string the first time calling
// this function. Supply NULL for subsequent call to get
// next sz string in multisz.
//
//-----------------------------------------------------------------------
LPCTSTR MultiSzTok( LPCTSTR lpMultiSz // Pointer to multisz string
) { LPCTSTR lpCurrentSz; static LPCTSTR lpNextSz;
if (lpMultiSz != NULL) { lpNextSz = lpMultiSz; }
lpCurrentSz = lpNextSz;
// Advance pointer to next Sz
while (*lpNextSz != TEXT('\0')) { lpNextSz++; } lpNextSz++;
return (*lpCurrentSz == TEXT('\0') ? NULL : lpCurrentSz); }
//-----------------------------------------------------------------------
//
// Function: CmpMultiSzi
//
// Descrip: check whether 2 multisz is equal(case insensitive)
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: here if stra ="foo1\0foo2\0" and strb = "foo2\0foo1\0"
// it will return equal , in other words, the string order
// in multi-sz is not playing role in comparing
//
//-----------------------------------------------------------------------
BOOL CmpMultiSzi( LPCTSTR szMultiSz1, LPCTSTR szMultiSz2) { LPCTSTR p;
if (MultiSzLen(szMultiSz1) != MultiSzLen(szMultiSz2)) { return FALSE; } p = szMultiSz1; while (*p) { if (!IsStrInMultiSz(p,szMultiSz2)) { return FALSE; } p += (lstrlen(p) + 1); } return TRUE; }
//-----------------------------------------------------------------------
//
// Function: AppendSzToMultiSz
//
// Descrip: appending a string to multiSZ
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: return true if succeed, since it will do malloc and the current multiSZ
// string buffer is too small to append a string, so the API will possible
// return false, call GetLastError to get error code
//
//-----------------------------------------------------------------------
BOOL AppendSzToMultiSz( IN LPCTSTR SzToAppend, IN OUT LPTSTR *MultiSz, IN OUT PDWORD pcchMultiSzLen //MultiSz buffer size in char
) { DWORD cchszLen; DWORD cchmultiSzLen; LPTSTR newMultiSz = NULL; LPTSTR lpStartPoint = NULL; LPTSTR lpSpTChar = NULL; BOOL bMemEnlarged = FALSE; DWORD cchLen; BOOL bRet = FALSE; HRESULT hr;
//SzToAppend can not be null or empty
if (!SzToAppend || !SzToAppend[0]) { SetLastError(ERROR_INVALID_PARAMETER); goto Exit; } //Multi-SZ must be initialzed , not NULL pointer, at least 2 '\0'
if (!MultiSz || *pcchMultiSzLen < 2) { SetLastError(ERROR_INVALID_PARAMETER); goto Exit; }
// get the size, of the two buffers in TCHAR
cchszLen = lstrlen(SzToAppend)+1; cchmultiSzLen = MultiSzLen(*MultiSz);
if (cchszLen + cchmultiSzLen > *pcchMultiSzLen) { newMultiSz = (LPTSTR)malloc( (cchszLen+cchmultiSzLen+MULTI_SZ_BUF_DELTA) * sizeof(TCHAR) ); if( newMultiSz == NULL ) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Exit; } // recopy the old MultiSz into proper position into the new buffer.
// the (char*) cast is necessary, because newMultiSz may be a wchar*, and
// szLen is in bytes.
memcpy( ((char*)newMultiSz), *MultiSz, cchmultiSzLen * sizeof(TCHAR)); bMemEnlarged = TRUE; cchLen = cchszLen + cchmultiSzLen + MULTI_SZ_BUF_DELTA; } else { newMultiSz = *MultiSz; cchLen = *pcchMultiSzLen; }
//the existing sz ended with 2 NULL, we need to start to copy the string
// from second null char
//lpStartPoint = (char*)newMultiSz + (multiSzLen - 1) * sizeof(TCHAR);
if (cchmultiSzLen == 2) { //if it's empty MultiSz, we do not need to keep the 1st NULL
cchmultiSzLen = 0; lpStartPoint = newMultiSz; } else { lpStartPoint = newMultiSz + (cchmultiSzLen - 1); } // copy in the new string
lpSpTChar = (TCHAR*) lpStartPoint; if (FAILED(hr = StringCchCopy(lpSpTChar,cchLen - (cchmultiSzLen - 1) , SzToAppend ))) { SetLastError(HRESULT_CODE(hr)); goto Exit; } //Add the ending NULL
*(lpSpTChar+lstrlen(SzToAppend)+1) = 0;
if (bMemEnlarged) { free( *MultiSz ); *MultiSz = newMultiSz; *pcchMultiSzLen = cchszLen + cchmultiSzLen + MULTI_SZ_BUF_DELTA; } SetLastError(ERROR_SUCCESS); bRet = TRUE; Exit: if (!bRet) { if (newMultiSz) { free(newMultiSz); } } return bRet; }
//-----------------------------------------------------------------------
//
// Function: PrintMultiSz
//
// Descrip:
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes: internal used for debug perpose
//
//-----------------------------------------------------------------------
void PrintMultiSz(LPTSTR MultiSz) { TCHAR *p = MultiSz;
while (*p) { _tprintf(TEXT(" %s"),p); _tprintf(TEXT("\n")); p += (lstrlen(p) + 1); }
}
//-----------------------------------------------------------------------
//
// Function: GetSetUserProfilePath
//
// Descrip: Get or Set User Profile path from registry
//
// Returns: BOOL
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
// szUserName: User name
// szPath : Profile path for set and buffer to get profile path for read
// nOperation: PROFILE_PATH_READ for get path and PROFILE_PATH_WRITE for
// set path
// nType : Specifes string type, only used to read though
// REG_SZ : for unicode string
// REG_EXPAND_SZ : for unicode string conatins enviroment variable
//
//-----------------------------------------------------------------------
HRESULT GetSetUserProfilePath( LPCTSTR szUserName, LPTSTR szPath, size_t cchPath, UINT nOperation, UINT nType) { PSID pSID =NULL; DWORD cbSID = 1024; TCHAR lpszDomain[MAXDOMAINLENGTH]; DWORD cchDomainName = MAXDOMAINLENGTH; SID_NAME_USE snuType; LPTSTR szStrSid = NULL; LPTSTR lpszRegRegProfilePath = NULL; HKEY hKeyProfileList = NULL; DWORD dwErr, dwType, cbUserProfilePath; DWORD dwSize; size_t cchLen; TCHAR szUserProfilePath[MAX_PATH],szExpandedUserProfilePath[MAX_PATH]; LPTSTR lpszUserProfilePath = szUserProfilePath; LPTSTR lpszExpandedUserProfilePath = szExpandedUserProfilePath; HRESULT hr;
pSID = (PSID) LocalAlloc(LPTR, cbSID); if (!pSID) { hr = E_OUTOFMEMORY; goto Cleanup; }
if (!LookupAccountName(NULL,szUserName,pSID,&cbSID,lpszDomain, &cchDomainName,&snuType)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } if (!IsValidSid(pSID)) { hr = E_FAIL; goto Cleanup; } if (!ConvertSidToStringSid(pSID,&szStrSid)) { hr = E_FAIL; goto Cleanup; }
cchLen = lstrlen(g_cszProfileList)+ lstrlen(szStrSid) + 3; if (!(lpszRegRegProfilePath = malloc(cchLen * sizeof(TCHAR)))) { hr = E_OUTOFMEMORY; goto Cleanup; } if (FAILED(hr = StringCchPrintf(lpszRegRegProfilePath,cchLen,_T("%s\\%s"),g_cszProfileList,szStrSid))) { goto Cleanup; } if ( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, lpszRegRegProfilePath, 0, KEY_ALL_ACCESS, &hKeyProfileList )) != ERROR_SUCCESS )
{ hr = HRESULT_FROM_WIN32(dwErr); goto Cleanup; }
if (nOperation == PROFILE_PATH_READ) { cbUserProfilePath = MAX_PATH; dwErr = RegQueryValueEx( hKeyProfileList, g_cszProfileImagePath, NULL, &dwType, (PBYTE)lpszUserProfilePath, &cbUserProfilePath ); if (dwErr == ERROR_MORE_DATA) { lpszUserProfilePath = malloc(cbUserProfilePath * sizeof(TCHAR)); if (!lpszUserProfilePath) { hr = E_OUTOFMEMORY; goto Cleanup; } dwErr = RegQueryValueEx(hKeyProfileList, g_cszProfileImagePath, NULL, &dwType, (PBYTE)lpszUserProfilePath, &cbUserProfilePath ); } } else { // for witre operation
dwErr = RegSetValueEx(hKeyProfileList, g_cszProfileImagePath, 0, REG_EXPAND_SZ, (const BYTE *)szPath, (lstrlen(szPath)+1)*sizeof(TCHAR)); }
if ( dwErr != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } //The string saved in registry contains enviroment variable, so
//if user want expanded version, we will do it here
if (nOperation == PROFILE_PATH_READ) { if (nType == REG_SZ) { size_t cchLenForExpandedStr; cchLenForExpandedStr = ExpandEnvironmentStrings( lpszUserProfilePath, lpszExpandedUserProfilePath, MAX_PATH); if (!cchLenForExpandedStr) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } else if (cchLenForExpandedStr >= MAX_PATH) { lpszExpandedUserProfilePath = malloc(cchLenForExpandedStr * sizeof(TCHAR)); if (!lpszExpandedUserProfilePath) { hr = E_OUTOFMEMORY; goto Cleanup; } if (!ExpandEnvironmentStrings(lpszUserProfilePath, lpszExpandedUserProfilePath, cchLenForExpandedStr)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } } if (FAILED(hr = StringCchCopy(szPath,cchPath,lpszExpandedUserProfilePath))) { goto Cleanup; } } else { if (FAILED(StringCchCopy(szPath,cchPath,lpszUserProfilePath))) { goto Cleanup; } } }
hr = S_OK;
Cleanup: if (hKeyProfileList) { RegCloseKey( hKeyProfileList ); } if (pSID) { FreeSid(pSID); } if (szStrSid) { LocalFree(szStrSid); } FreePointer(lpszRegRegProfilePath); if (!lpszUserProfilePath && (lpszUserProfilePath != szUserProfilePath)) { free(lpszUserProfilePath); } if (!lpszExpandedUserProfilePath && (lpszExpandedUserProfilePath != szUserProfilePath)) { free(lpszExpandedUserProfilePath); } return (hr); }
//-----------------------------------------------------------------------
//
// Function: ReStartSystem
//
// Descrip: logoff or reboot the system
//
// Returns: none
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
//
//-----------------------------------------------------------------------
void ReStartSystem(UINT uFlags) { HANDLE Token = NULL; ULONG ReturnLength, Index; PTOKEN_PRIVILEGES NewState = NULL; PTOKEN_PRIVILEGES OldState = NULL; BOOL Result;
Result = OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token ); if (Result) { ReturnLength = 4096; NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength); OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength); Result = (BOOL)((NewState != NULL) && (OldState != NULL)); if (Result) { Result = GetTokenInformation( Token, // TokenHandle
TokenPrivileges, // TokenInformationClass
NewState, // TokenInformation
ReturnLength, // TokenInformationLength
&ReturnLength ); // ReturnLength
if (Result) { //
// Set the state settings so that all privileges are enabled...
//
if (NewState->PrivilegeCount > 0) { for (Index = 0; Index < NewState->PrivilegeCount; Index++) { NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED; } }
Result = AdjustTokenPrivileges( Token, // TokenHandle
FALSE, // DisableAllPrivileges
NewState, // NewState
ReturnLength, // BufferLength
OldState, // PreviousState
&ReturnLength ); // ReturnLength
if (Result) { //ExitWindowsEx(uFlags, 0);
InitiateSystemShutdownEx(NULL,NULL,0,TRUE,TRUE, SHTDN_REASON_MAJOR_OPERATINGSYSTEM|SHTDN_REASON_MINOR_UPGRADE); AdjustTokenPrivileges( Token, FALSE, OldState, 0, NULL, NULL ); } } } }
if (NewState != NULL) { LocalFree(NewState); } if (OldState != NULL) { LocalFree(OldState); } if (Token != NULL) { CloseHandle(Token); } }
//-----------------------------------------------------------------------
//
// Function: DoMessageBox
//
// Descrip: Wrapper for MessageBox
//
// Returns: UINT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
//
//-----------------------------------------------------------------------
int DoMessageBox(HWND hwndParent, UINT uIdString, UINT uIdCaption, UINT uType) { TCHAR szString[MAX_PATH+MAX_PATH]; TCHAR szCaption[MAX_PATH];
szString[0] = szCaption[0] = TEXT('\0');
if (uIdString) LoadString(g_hInstDll, uIdString, szString, MAX_PATH+MAX_PATH-1);
if (uIdCaption) LoadString(g_hInstDll, uIdCaption, szCaption, MAX_PATH-1);
return MessageBox(hwndParent, szString, szCaption, uType); }
//-----------------------------------------------------------------------
//
// Function: DoMessageBox
//
// Descrip: Wrapper for MessageBox
//
// Returns: UINT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
// Notes:
//
//-----------------------------------------------------------------------
BOOL Str2KeyPath( IN LPTSTR String, OUT PHKEY Data, OUT LPTSTR *pSubKeyPath ) { UINT i; TCHAR *p,ch; DWORD cchStrlen;
STRING_TO_DATA InfRegSpecTohKey[] = { TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE, TEXT("HKLM") , HKEY_LOCAL_MACHINE, TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT, TEXT("HKCR") , HKEY_CLASSES_ROOT, TEXT("HKR") , NULL, TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER, TEXT("HKCU") , HKEY_CURRENT_USER, TEXT("HKEY_USERS") , HKEY_USERS, TEXT("HKU") , HKEY_USERS, TEXT("") , NULL };
PSTRING_TO_DATA Table = InfRegSpecTohKey;
if ( !String || !String[0]) { *pSubKeyPath = NULL; *Data = NULL; return TRUE; } for(i=0; Table[i].String[0]; i++) { cchStrlen = _tcslen(Table[i].String); if (_tcslen(String) < cchStrlen) { continue; } ch = String[cchStrlen]; String[cchStrlen] = 0; if(!MyStrCmpI(Table[i].String,String)) { *Data = Table[i].Data; String[cchStrlen] = ch; *pSubKeyPath = &(String[cchStrlen+1]); return(TRUE); } String[cchStrlen] = ch; } //if we can not find the prefix defined
//we think it's for user registery
//In this case ,we return PHKEY as NULL, and pSubKeyPath = String
*pSubKeyPath = String; *Data = NULL; return TRUE; }
BOOL HKey2Str( IN HKEY hKey, IN LPTSTR pKeyPath, IN size_t cbKeyPath ) { UINT i; TCHAR *p,ch; size_t nStrlen;
STRING_TO_DATA InfRegSpecTohKey[] = { TEXT("HKLM") , HKEY_LOCAL_MACHINE, TEXT("HKCR") , HKEY_CLASSES_ROOT, TEXT("HKCU") , HKEY_CURRENT_USER, TEXT("HKU") , HKEY_USERS, TEXT("") , NULL };
PSTRING_TO_DATA Table = InfRegSpecTohKey;
for(i=0; Table[i].Data; i++) { if (hKey == Table[i].Data) { if (SUCCEEDED(StringCchCopy(pKeyPath,cbKeyPath,Table[i].String))) { return TRUE; } else { return FALSE; } } } return(FALSE); }
//-----------------------------------------------------------------------------
//
// Function: Str2KeyPath2
//
// Synopsis: Return the HKEY_xxx value associcated with string value
//
// Returns: REG_xxx value
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL Str2KeyPath2( LPCTSTR lpHKeyStr, PHKEY pHKey, LPCTSTR* pSubKeyPath ) { int i; LPCTSTR lpStart;
STRING_TO_DATA InfRegSpecTohKey[] = { TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE, TEXT("HKLM") , HKEY_LOCAL_MACHINE, TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT, TEXT("HKCR") , HKEY_CLASSES_ROOT, TEXT("HKR") , NULL, TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER, TEXT("HKCU") , HKEY_CURRENT_USER, TEXT("HKEY_USERS") , HKEY_USERS, TEXT("HKU") , HKEY_USERS, TEXT("") , NULL };
PSTRING_TO_DATA Table = InfRegSpecTohKey;
if (NULL == lpHKeyStr) { return FALSE; }
for(i = 0 ; Table[i].String[0] != TEXT('\0') ; i++) { lpStart = _tcsstr(lpHKeyStr, Table[i].String); if (lpStart == lpHKeyStr) { //
// Assign the values back to caller, if caller supply the pointers
//
if (NULL != pHKey) { *pHKey = Table[i].Data; }
if (NULL != pSubKeyPath) { lpStart += lstrlen(Table[i].String); if (*lpStart == TEXT('\0')) { *pSubKeyPath = lpStart; } else { *pSubKeyPath = lpStart + 1; } } return TRUE; } }
return FALSE; }
//-----------------------------------------------------------------------------
//
// Function: Str2REG
//
// Synopsis: Convert the registry type string to REG_xxx value
//
// Returns: REG_xxx value
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
DWORD Str2REG( LPCTSTR lpStrType // String of registry type
) { INT nIndex;
struct _STRING_TO_REG { TCHAR szStrType[32]; DWORD dwType; };
// Mapping table from string to REG_xxx value
struct _STRING_TO_REG arrRegEntries[] = { TEXT("REG_BINARY"), REG_BINARY, TEXT("REG_DWORD"), REG_DWORD, TEXT("REG_DWORD_LITTLE_ENDIAN"), REG_DWORD_LITTLE_ENDIAN, TEXT("REG_DWORD_BIG_ENDIAN"), REG_DWORD_BIG_ENDIAN, TEXT("REG_EXPAND_SZ"), REG_EXPAND_SZ, TEXT("REG_LINK"), REG_LINK, TEXT("REG_MULTI_SZ"), REG_MULTI_SZ, TEXT("REG_NONE"), REG_NONE, TEXT("REG_QWORD"), REG_QWORD, TEXT("REG_QWORD_LITTLE_ENDIAN"), REG_QWORD_LITTLE_ENDIAN, TEXT("REG_RESOUCE_LIST"), REG_RESOURCE_LIST, TEXT("REG_SZ"), REG_SZ, TEXT(""), 0 };
if (lpStrType == NULL) { return REG_NONE; }
for (nIndex = 0 ; arrRegEntries[nIndex].szStrType[0] != TEXT('\0') ; nIndex++) { if (MyStrCmpI(lpStrType, arrRegEntries[nIndex].szStrType) == 0) { return arrRegEntries[nIndex].dwType; } }
return REG_NONE; }
//*************************************************************
// GetFirstEnvStrLen
//
// Purpose: Get the environment string length if it is at the beginning.
//
// Parameter: lpStr: Input string
//
// Notes: none
//
// History: 3/25/2001 geoffguo created
//*************************************************************
DWORD GetFirstEnvStrLen (LPTSTR lpStr) { DWORD dwLen = 0; DWORD dwSize, i; TCHAR cTemp;
if (lpStr[0] == L'%') { dwSize = lstrlen(lpStr); for (i = 1; i < dwSize; i++) if (lpStr[i] == L'%') break;
if (i < dwSize) { cTemp = lpStr[i+1]; lpStr[i+1] = (TCHAR)'\0'; dwLen = ExpandEnvironmentStrings (lpStr, NULL, 0); lpStr[i+1] = cTemp; } }
return dwLen; }
//*************************************************************
// StringValidationCheck
//
// Purpose: Check the string to see if it is a valid system path
//
// Parameter: lpOriginalStr: Data string to be checked
// lpSearchStr: Search string
// lpSysPath: Point to standard system path
// lpszTailCheck: Point to predefined tail character
// lpAttrib: Folder attribute
// dwStrNum: The number of matching string
//
// Notes: none
//
// History: 3/18/2001 geoffguo created
//*************************************************************
BOOL StringValidationCheck ( LPCTSTR lpOriginalStr, LPCTSTR lpSearchStr, LPCTSTR lpSysPath, LPCTSTR lpTailCheck, LPDWORD lpAttrib, DWORD dwStrNum) { BOOL bRet = TRUE; DWORD i, dwLen; LPTSTR lpOrgStr, lpTemp1, lpTemp2;
if (lpAttrib == NULL || lpSysPath == NULL) goto Exit;
dwLen = ExpandEnvironmentStrings (lpOriginalStr, NULL, 0); if (dwLen == 0) { bRet = FALSE; goto Exit; } lpOrgStr = calloc (dwLen+1, sizeof(TCHAR)); if (!lpOrgStr) { bRet = FALSE; goto Exit; } ExpandEnvironmentStrings (lpOriginalStr, lpOrgStr, dwLen+1);
dwLen = lstrlen(lpSearchStr); //To avoid hit Documents and Settings wrongly,
//skip the environment variable at the beginning of the string.
lpTemp1 = lpOrgStr + GetFirstEnvStrLen((LPTSTR)lpOriginalStr);
for (i = 0; i < dwStrNum; i++) { lpTemp2 = StrStrI(lpTemp1, lpSearchStr); if (!lpTemp2) { bRet = FALSE; goto Exit1; } lpTemp1 = lpTemp2+dwLen; }
if (*(lpTemp2+dwLen) == *lpTailCheck) { bRet = FALSE; goto Exit1; } if (StrStrI(lpOriginalStr, L"\\Device\\HarddiskVolume")) { bRet = TRUE; goto Exit1; }
switch (*lpAttrib & 0xffff) { /*
CSIDL_DESKTOP // <desktop>
CSIDL_INTERNET // Internet Explorer (icon on desktop)
CSIDL_CONTROLS // My Computer\Control Panel
CSIDL_PRINTERS // My Computer\Printers
CSIDL_BITBUCKET // <desktop>\Recycle Bin
CSIDL_MYDOCUMENTS // logical "My Documents" desktop icon
CSIDL_DRIVES // My Computer
CSIDL_NETWORK // Network Neighborhood (My Network Places)
CSIDL_FONTS // windows\fonts
CSIDL_ALTSTARTUP // non localized startup
CSIDL_COMMON_ALTSTARTUP // non localized common startup
CSIDL_WINDOWS // GetWindowsDirectory()
CSIDL_SYSTEM // GetSystemDirectory()
CSIDL_CONNECTIONS // Network and Dial-up Connections
CSIDL_PROFILE // USERPROFILE
CSIDL_SYSTEMX86 // x86 system directory on RISC
CSIDL_PROGRAM_FILESX86 // x86 C:\Program Files on RISC
CSIDL_PROGRAM_FILES_COMMONX86 // x86 Program Files\Common on RISC
CSIDL_RESOURCES // Resource Direcotry
CSIDL_RESOURCES_LOCALIZED // Localized Resource Direcotry
CSIDL_COMMON_OEM_LINKS // Links to All Users OEM specific apps
CSIDL_COMPUTERSNEARME // Computers Near Me (computered from Workgroup membership)
*/ case CSIDL_COMMON_APPDATA: // All Users\Application Data
case CSIDL_COMMON_DESKTOPDIRECTORY: // All Users\Desktop
case CSIDL_COMMON_STARTMENU: // All Users\Start Menu
case CSIDL_COMMON_TEMPLATES: // All Users\Templates
case CSIDL_COMMON_FAVORITES: case CSIDL_COMMON_STARTUP: // All Users\Start Menu\Startup
case CSIDL_COMMON_MUSIC: // All Users\My Music
case CSIDL_COMMON_PICTURES: // All Users\My Pictures
case CSIDL_COMMON_VIDEO: // All Users\My Video
case CSIDL_COMMON_ADMINTOOLS: // All Users\Start Menu\Programs\Administrative Tools
case CSIDL_COMMON_PROGRAMS: // All Users\Start Menu\Programs
case CSIDL_COMMON_ACCESSORIES: // All Users\Start Menu\Programs\Accessaries
case CSIDL_COMMON_DOCUMENTS: // All Users\Documents
case CSIDL_STARTMENU: // <user name>\Start Menu
case CSIDL_DESKTOPDIRECTORY: // <user name>\Desktop
case CSIDL_NETHOOD: // <user name>\nethood
case CSIDL_TEMPLATES: // <user name>\Templates
case CSIDL_APPDATA: // <user name>\Application Data
case CSIDL_LOCAL_SETTINGS: // <user name>\Local Settings
case CSIDL_PRINTHOOD: // <user name>\PrintHood
case CSIDL_FAVORITES: // <user name>\Favorites
case CSIDL_RECENT: // <user name>\Recent
case CSIDL_SENDTO: // <user name>\SendTo
case CSIDL_COOKIES: // <user name>\Cookies
case CSIDL_HISTORY: // <user name>\History
case CSIDL_PERSONAL: // <user name>\My Documents
case CSIDL_MYMUSIC: // <user name>\My Document\My Music
case CSIDL_MYPICTURES: // <user name>\My Document\My Pictures
case CSIDL_ADMINTOOLS: // <user name>\Start Menu\Programs\Administrative Tools
case CSIDL_PROGRAMS: // <user name>\Start Menu\Programs
case CSIDL_STARTUP: // <user name>\Start Menu\Programs\Startup
case CSIDL_ACCESSORIES: // <user name>\Start Menu\Programs\Accessaries
case CSIDL_LOCAL_APPDATA: // <user name>\Local Settings\Applicaiton Data (non roaming)
case CSIDL_INTERNET_CACHE: // <user name>\Local Settings\Temporary Internet Files
case CSIDL_PROGRAM_FILES_COMMON: // C:\Program Files\Common
case CSIDL_PF_ACCESSORIES: // C:\Program Files\Accessaries
case CSIDL_PROGRAM_FILES: // C:\Program Files
case CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES: //for %CommonProgramFiles%\services
case CSIDL_COMMON_PROGRAMFILES_ACCESSARIES: //for %ProgramFiles%\accessaries
case CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES: //for %ProgramFiles%\Windows NT\accessaries
case CSIDL_MYVIDEO: // "My Videos" folder
case CSIDL_CDBURN_AREA: // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
case CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY: case CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT: case CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS: case CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS: case CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER: case CSIDL_COMMON_ACCESSORIES_GAMES: case CSIDL_COMMON_WINDOWSMEDIA: case CSIDL_COMMON_COVERPAGES: case CSIDL_COMMON_RECEIVED_FAX: case CSIDL_COMMON_SENT_FAX: case CSIDL_COMMON_FAX: case CSIDL_FAVORITES_LINKS: case CSIDL_FAVORITES_MEDIA: case CSIDL_ACCESSORIES_ACCESSIBILITY: case CSIDL_ACCESSORIES_SYSTEM_TOOLS: case CSIDL_ACCESSORIES_ENTERTAINMENT: case CSIDL_ACCESSORIES_COMMUNICATIONS: case CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL: case CSIDL_PROFILES_DIRECTORY: case CSIDL_USERNAME_IN_USERPROFILE: case CSIDL_UAM_VOLUME: case CSIDL_COMMON_SHAREDTOOLS_STATIONERY: case CSIDL_NETMEETING_RECEIVED_FILES: case CSIDL_COMMON_NETMEETING_RECEIVED_FILES: case CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX: case CSIDL_FAX_PERSONAL_COVER_PAGES: case CSIDL_FAX: bRet = ReverseStrCmp(lpTemp2, lpSysPath); break; default: break; }
Exit1: free (lpOrgStr);
Exit: return bRet; }
//*************************************************************
// ReplaceMultiMatchInString
//
// Purpose: Replace the string at multiple place in data string
//
// Parameter: lpOldStr: Data string to be checked
// lpNewStr: Output string buffer
// cbNewStr: Size of output string buffer
// dwMaxMatchNum: Max posible match number
// lpRegStr: String and attribute table
// bStrCheck: True -- do it, or False -- skip it
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//*************************************************************
BOOL ReplaceMultiMatchInString( LPTSTR lpOldStr, LPTSTR lpNewStr, size_t cbNewStr, DWORD dwMaxMatchNum, PREG_STRING_REPLACE lpRegStr, LPDWORD pAttrib, BOOL bStrCheck) { BOOL bRet = FALSE; LPCTSTR lpSearchStr; LPCTSTR lpReplaceStr; LPTSTR lpMiddleStr; LPCTSTR lpPath; LPDWORD lpAttrib; TCHAR cNonChar = L'\xFFFF'; TCHAR cSpaceChar = L' '; TCHAR cDotChar = L'.'; TCHAR cRightChar; DWORD cchMiddleStr;
cchMiddleStr = lstrlen(lpOldStr) + lpRegStr->cchMaxStrLen * dwMaxMatchNum; lpMiddleStr = (LPTSTR) calloc(cchMiddleStr, sizeof(TCHAR)); if (!lpMiddleStr) { goto Exit; }
if (FAILED(StringCchCopy(lpMiddleStr, cchMiddleStr,lpOldStr))) { goto Exit; } lpSearchStr = lpRegStr->lpSearchString; lpReplaceStr = lpRegStr->lpReplaceString; lpAttrib = lpRegStr->lpAttrib; if (lpRegStr->lpFullStringList) { lpPath = lpRegStr->lpFullStringList; } else { lpPath = NULL; } while (*lpSearchStr && *lpReplaceStr) { if (bStrCheck) { if (*lpAttrib == CSIDL_COMMON_DOCUMENTS) { cRightChar = cSpaceChar; } else if (*lpAttrib == CSIDL_USERNAME_IN_USERPROFILE) { cRightChar = cDotChar; } else { cRightChar = cNonChar; } }
if(ReplaceString(lpMiddleStr, lpSearchStr, lpReplaceStr, lpNewStr, cchMiddleStr, &cRightChar, lpPath, lpAttrib, bStrCheck)) { if (bStrCheck) { *pAttrib |= *lpAttrib; } bRet = TRUE; }
if (FAILED(StringCchCopy(lpMiddleStr, cchMiddleStr,lpNewStr))) goto Exit;
lpSearchStr += lstrlen(lpSearchStr) + 1; lpReplaceStr += lstrlen(lpReplaceStr) + 1; if (lpPath) { lpPath += lstrlen(lpPath) + 1; } if (lpAttrib) { lpAttrib++; } } Exit: if(lpMiddleStr) { free(lpMiddleStr); } return bRet; }
//-----------------------------------------------------------------------------
//
// Function: ComputeLocalProfileName
//
// Synopsis: Constructs the pathname of the local profile for user.
// It will attempt to create user profile directory using
// username. If the directory exists, it will append a counter
// after users name e.g. %documentsettings%\username.001
//
// Returns: TRUE if succeeded, FALSE otherwise
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
BOOL ComputeLocalProfileName( LPCTSTR lpOldUserName, // Old user name
LPCTSTR lpNewUserName, // New user name
LPTSTR lpNewProfilePath, // Output buffer store new profile path
size_t cchNewProfilePath, // Size of profile path buffer (in WCHAR)
UINT nRegType // Read the output in REG_SZ or REG_EXPAND_SZ
) { HANDLE hFile; TCHAR szProfilePath[MAX_PATH]; TCHAR szUserProfilePath[MAX_PATH]; TCHAR szExpUserProfilePath[MAX_PATH]; TCHAR szComputerName[16]; DWORD cbSize; DWORD dwType; LONG lRet; DWORD cchSize; size_t nCounter; HKEY hKey; HRESULT hr; WIN32_FIND_DATA fd;
if (lpOldUserName == NULL || lpOldUserName[0] == TEXT('\0') || lpNewUserName == NULL || lpNewUserName[0] == TEXT('\0') || lpNewProfilePath == NULL) { return FALSE; }
//
// If user name does not change, return the current user's profile path
//
if (MyStrCmpI(lpOldUserName, lpNewUserName) == 0) { hr = GetSetUserProfilePath(lpOldUserName, lpNewProfilePath, cchNewProfilePath, PROFILE_PATH_READ, nRegType); if (SUCCEEDED(hr)) { return TRUE; } else { return FALSE; } }
//
// Get ProfilesDirectory from registry
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_cszProfileList, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { cbSize = sizeof(szProfilePath); lRet = RegQueryValueEx(hKey, PROFILES_DIRECTORY, NULL, &dwType, (LPBYTE) szProfilePath, &cbSize); RegCloseKey(hKey);
if (lRet != ERROR_SUCCESS) { DPF(dlError, TEXT("ComputeLocalProfileName: Unable to query reg value <%s>"), PROFILES_DIRECTORY); return FALSE; } } else { DPF(dlError, TEXT("ComputeLocalProfileName: Unable to open reg key <%s>"), g_cszProfileList); return FALSE; }
// Compose a new user profile directory
hr = StringCchPrintf(szUserProfilePath, ARRAYSIZE(szUserProfilePath), TEXT("%s\\%s"), szProfilePath, lpNewUserName); if ( FAILED(hr) ) { return FALSE; }
// Profile path still contains environment strings, need to expand it
ExpandEnvironmentStrings(szUserProfilePath, szExpUserProfilePath, ARRAYSIZE(szExpUserProfilePath));
// Does this directory exist?
hFile = FindFirstFile(szExpUserProfilePath, &fd); if (INVALID_HANDLE_VALUE == hFile) { //
// Directory does not exist, use this name
//
hr = StringCchCopy(lpNewProfilePath, cchNewProfilePath, szUserProfilePath); if ( FAILED(hr) ) { return FALSE; }
return TRUE; } else { //
// Directory exists, try different name
//
FindClose(hFile);
// Try appending username with computer Name
cchSize = ARRAYSIZE(szComputerName); GetComputerName(szComputerName, &cchSize);
hr = StringCchPrintf(szUserProfilePath, ARRAYSIZE(szUserProfilePath), TEXT("%s\\%s.%s"), szProfilePath, lpNewUserName, szComputerName); if ( FAILED(hr) ) { return FALSE; }
// Profile path still contains environment strings, need to expand it
ExpandEnvironmentStrings(szUserProfilePath, szExpUserProfilePath, ARRAYSIZE(szExpUserProfilePath));
// Does the new directory name exist?
hFile = FindFirstFile(szExpUserProfilePath, &fd); if (INVALID_HANDLE_VALUE == hFile) { // Directory does not exist, use this one
hr = StringCchCopy(lpNewProfilePath, cchNewProfilePath, szUserProfilePath); if ( FAILED(hr) ) { return FALSE; }
return TRUE; } else { //
// This directory also exists
//
FindClose(hFile);
for (nCounter = 0 ; nCounter < 1000 ; nCounter++) { // Try appending counter after user name
hr = StringCchPrintf(szUserProfilePath, ARRAYSIZE(szUserProfilePath), TEXT("%s\\%s.%.3d"), szProfilePath, lpNewUserName, nCounter); if ( FAILED(hr) ) { return FALSE; }
// Profile path still contains environment strings, need to expand it
ExpandEnvironmentStrings(szUserProfilePath, szExpUserProfilePath, ARRAYSIZE(szExpUserProfilePath));
// Does this directory name exist?
hFile = FindFirstFile(szExpUserProfilePath, &fd); if (INVALID_HANDLE_VALUE == hFile) { // Directory does not exist, use this one
hr = StringCchCopy(lpNewProfilePath, cchNewProfilePath, szUserProfilePath); if ( FAILED(hr) ) { return FALSE; }
return TRUE; } else { // Directory exists, keep finding...
FindClose(hFile); } } } }
// If we reach here, we could not find a new profile directory for this user
return FALSE; }
//-----------------------------------------------------------------------------
//
// Function: UpdateProgress
//
// Synopsis: Simple progress clock, display the progress during
// long operation.
//
// Returns: none.
//
// History: 02/07/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
void UpdateProgress() { static unsigned short n; const TCHAR clock[] = TEXT("-\\|/");
wprintf(TEXT("%lc\r"), clock[n]); n++; n %= 4; }
//-----------------------------------------------------------------------//
//
// GetMaxStrLen()
//
// Get Maximum searching strings and replace strings length for string
// buffer memery allocation.
//
// lpRegStr: Input parameter structure
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
DWORD GetMaxStrLen ( PREG_STRING_REPLACE lpRegStr) { DWORD dwLen = 0; DWORD dwMaxLen; LPTSTR lpStr;
lpStr = lpRegStr->lpReplaceString; dwMaxLen = 0;
while (*lpStr) { dwLen = lstrlen(lpStr);
//dwMaxLen is the max-length in replacement multi-strings
if (dwLen > dwMaxLen) dwMaxLen = dwLen;
lpStr += dwLen + 1; }
lpStr = lpRegStr->lpSearchString; while (*lpStr) { dwLen = lstrlen(lpStr);
//dwMaxLen is the max-length in search and replacement multi-strings
if (dwLen > dwMaxLen) dwMaxLen = dwLen;
lpStr += dwLen + 1; }
return dwMaxLen; }
//-----------------------------------------------------------------------//
//
// AddNodeToList()
//
// lpVal: The node needed to add.
// lpValList: The head of the list.
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
DWORD AddNodeToList ( PVALLIST lpVal, PVALLIST *lpValList) { DWORD nResult = ERROR_SUCCESS; PVALLIST lpTemp;
if (!*lpValList) { *lpValList = lpVal; } else { lpTemp = *lpValList;
while (lpTemp->pvl_next) lpTemp = lpTemp->pvl_next; lpTemp->pvl_next = lpVal; }
return nResult; }
//-----------------------------------------------------------------------//
//
// RemoveValueList()
//
// lpValList: The head of the list.
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
DWORD RemoveValueList ( PVALLIST *lpValList) { DWORD nResult = ERROR_SUCCESS; PVALLIST lpTemp, lpDel;
if (*lpValList) { lpTemp = *lpValList;
while (lpTemp) { lpDel = lpTemp; lpTemp = lpTemp->pvl_next; if (lpDel->ve.ve_valuename) free (lpDel->ve.ve_valuename); if (lpDel->ve.ve_valueptr) free ((LPBYTE)(lpDel->ve.ve_valueptr)); if (lpDel->lpPre_valuename) free (lpDel->lpPre_valuename); free (lpDel); } }
return nResult; }
//-----------------------------------------------------------------------//
//
// FreeStrList()
//
// lpStrList: The head of the list.
//
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
void FreeStrList ( PSTRLIST lpStrList) { if (lpStrList->pst_next) FreeStrList (lpStrList->pst_next);
if (lpStrList->lpstr) free (lpStrList->lpstr);
free (lpStrList); }
//-----------------------------------------------------------------------//
//
// GetMaxMatchNum()
//
// Get maximum string match number.
//
// lpDataStr: Search string
// lpRegStr: Input parameter structure
//
// Notes: none
//
// History: 12/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
DWORD GetMaxMatchNum ( LPTSTR lpDataStr, PREG_STRING_REPLACE lpRegStr) { DWORD dwMatchNum, dwLen; LPTSTR lpTemp; LPTSTR lpSearchStr; LPTSTR lpFound;
lpSearchStr = lpRegStr->lpSearchString; dwMatchNum = 0;
while (*lpSearchStr) { lpTemp = lpDataStr;
while (lpFound = StrStrI(lpTemp, lpSearchStr)) { dwMatchNum++; lpTemp = lpFound + 1; } dwLen = lstrlen(lpSearchStr); lpSearchStr += dwLen + 1; }
return dwMatchNum; }
//-----------------------------------------------------------------------//
//
// ReplaceSingleString()
//
// DESCRIPTION:
// Analize a single string and replace localized string to English.
//
// lpOldDataStr: String data
// dwType: Type of string
// lpRegStr: Input parameter structure
// lpFullKey: Full sub-key path
//
// Notes: none
//
// History: 11/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
LPTSTR ReplaceSingleString ( LPTSTR lpOldDataStr, DWORD dwType, PREG_STRING_REPLACE lpRegStr, LPTSTR lpFullKey, LPDWORD pAttrib, BOOL bStrChk) { DWORD dwMatchNum; LPTSTR lpNewDataStr = NULL; size_t cbNewDataStr;
if (!lpOldDataStr) goto Exit;
dwMatchNum = GetMaxMatchNum (lpOldDataStr, lpRegStr);
if (dwMatchNum > 0) { if (dwType != REG_DWORD && *lpOldDataStr) { cbNewDataStr = lstrlen(lpOldDataStr) + lpRegStr->cchMaxStrLen * dwMatchNum; lpNewDataStr = (LPTSTR) calloc(cbNewDataStr, sizeof(TCHAR)); if (!lpNewDataStr) { DPF (dlError, L"ReplaceSingleString: No enough memory"); goto Exit; } if (!ReplaceMultiMatchInString(lpOldDataStr, lpNewDataStr, cbNewDataStr, dwMatchNum, lpRegStr, pAttrib, bStrChk)) { free (lpNewDataStr); lpNewDataStr = NULL; } } }
Exit: return lpNewDataStr; }
//-----------------------------------------------------------------------//
//
// ReplaceValueSettings()
//
// Rename value setting based on input parameter
//
// szUserName: User name
// lpOldDataStr: String value data
// dwSize: Size of string data
// lpOldValueName:Value name
// dwType: Type of string
// lpRegStr: Input parameter structure
// lpValList: Updated value list
// lpFullKey: Full sub-key path
//
// Notes: none
//
// History: 11/10/2001 geoffguo created
//
//-----------------------------------------------------------------------//
HRESULT ReplaceValueSettings ( LPTSTR szUserName, LPTSTR lpOldDataStr, DWORD dwSize, LPTSTR lpOldValueName, DWORD dwType, PREG_STRING_REPLACE lpRegStr, PVALLIST *lpValList, LPTSTR lpFullKey, BOOL bStrChk) { BOOL bValueName = FALSE; BOOL bValueData = FALSE; HRESULT hResult = S_OK; DWORD dwOutputSize = 0, dwMatchNum = 0; LPTSTR lpNewDataStr = NULL; LPTSTR lpNewValueName = NULL; LPTSTR lpOutputValueName; LPTSTR lpEnd; LPBYTE lpOutputData; PVALLIST lpVal = NULL; PSTRLIST lpStrList = NULL; PSTRLIST lpLastList = NULL; PSTRLIST lpTempList = NULL; size_t cbPre_valuename; DWORD dwAttrib = 0;
lpStrList = (PSTRLIST) calloc(sizeof(STRLIST), 1); lpLastList = lpStrList; if (!lpLastList) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings1: No enough memory"); goto Exit; } if ( (dwType & 0xffff)== REG_MULTI_SZ) { lpEnd = lpOldDataStr;
while(lpEnd < (lpOldDataStr + dwSize/sizeof(TCHAR))) { if(*lpEnd == (TCHAR)'\0') { //empty string
dwOutputSize += sizeof(TCHAR); lpEnd++; } else { lpNewDataStr = ReplaceSingleString ( lpEnd, dwType, lpRegStr, lpFullKey, &dwAttrib, bStrChk); if (lpNewDataStr) { lpLastList->lpstr = lpNewDataStr; bValueData = TRUE; } else { size_t cbBufLen = lstrlen(lpEnd)+1; lpLastList->lpstr = calloc(cbBufLen, sizeof(TCHAR)); if (!lpLastList->lpstr) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings2: No enough memory"); goto Exit; } hResult = StringCchCopy(lpLastList->lpstr, cbBufLen,lpEnd); if (FAILED(hResult)) { DPF (dlError, L"ReplaceValueSettings: buffer too small for %s",lpEnd); goto Exit; } }
dwOutputSize += (lstrlen(lpLastList->lpstr)+1)*sizeof(TCHAR); lpEnd += lstrlen(lpEnd)+1; } lpLastList->pst_next = (PSTRLIST) calloc(sizeof(STRLIST), 1); if (!lpLastList->pst_next) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings3: No enough memory"); goto Exit; }
lpLastList->pst_next->pst_prev = lpLastList; lpLastList = lpLastList->pst_next; lpLastList->pst_next = NULL; lpLastList->lpstr = NULL; } if (lpLastList != lpStrList) { lpLastList = lpLastList->pst_prev; free (lpLastList->pst_next); lpLastList->pst_next = NULL; } } else { lpNewDataStr = ReplaceSingleString ( lpOldDataStr, dwType, lpRegStr, lpFullKey, &dwAttrib, bStrChk);
if (lpNewDataStr) { lpLastList->lpstr = lpNewDataStr; bValueData = TRUE; } else { lpLastList->lpstr = calloc(dwSize+sizeof(TCHAR), 1); if (!lpLastList->lpstr) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings4: No enough memory"); goto Exit; }
hResult = StringCbCopy(lpLastList->lpstr, dwSize+sizeof(TCHAR), lpOldDataStr); if (FAILED(hResult)) { goto Exit; } }
lpLastList->pst_next = NULL; dwOutputSize = (lstrlen(lpLastList->lpstr)+1)*sizeof(TCHAR); }
if (lpOldValueName) dwMatchNum = GetMaxMatchNum (lpOldValueName, lpRegStr); else dwMatchNum = 0;
if (dwMatchNum > 0) { if (*lpOldValueName) { size_t cbNewValueName = lstrlen(lpOldValueName) + lpRegStr->cchMaxStrLen * dwMatchNum; lpNewValueName = (LPTSTR) calloc(cbNewValueName, sizeof(TCHAR)); if (!lpNewValueName) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings5: No enough memory"); goto Exit; } bValueName = ReplaceMultiMatchInString(lpOldValueName, lpNewValueName,cbNewValueName, dwMatchNum, lpRegStr, &dwAttrib, bStrChk); } }
if (bValueData || bValueName) { lpVal = (PVALLIST) calloc(sizeof(VALLIST), 1);
if (!lpVal) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings6: No enough memory"); goto Exit; }
if (bValueData) { lpVal->val_type |= REG_CHANGE_VALUEDATA; }
if (bValueName) { lpOutputValueName = lpNewValueName; lpVal->val_type |= REG_CHANGE_VALUENAME; } else lpOutputValueName = lpOldValueName; if (lpOutputValueName) { HRESULT hr; size_t cbValname = lstrlen(lpOutputValueName) + 1; lpVal->ve.ve_valuename = (LPTSTR) calloc(cbValname, sizeof(TCHAR)); if (!lpVal->ve.ve_valuename) { hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings7: No enough memory"); goto Exit; } //We calculte the buffer for lpVal->lpPre_valuename, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchCopy (lpVal->ve.ve_valuename, cbValname, lpOutputValueName); } else lpVal->ve.ve_valuename = NULL;
lpVal->ve.ve_valueptr = (DWORD_PTR) calloc(dwOutputSize, 1); if (!lpVal->ve.ve_valueptr) { free (lpVal->ve.ve_valuename); hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings8: No enough memory"); goto Exit; }
if (lpOldValueName) { cbPre_valuename = lstrlen(lpOldValueName)+1; lpVal->lpPre_valuename = (LPTSTR)calloc(cbPre_valuename, sizeof(TCHAR)); if (!lpVal->lpPre_valuename) { free (lpVal->ve.ve_valuename); free ((LPBYTE)(lpVal->ve.ve_valueptr)); hResult = E_OUTOFMEMORY; DPF (dlError, L"ReplaceValueSettings9: No enough memory"); goto Exit; } } else lpVal->lpPre_valuename = NULL;
lpVal->val_attrib = dwAttrib;
lpOutputData = (LPBYTE)(lpVal->ve.ve_valueptr);
lpTempList = lpStrList; do { if (lpTempList->lpstr) memcpy (lpOutputData, (LPBYTE)lpTempList->lpstr, (lstrlen(lpTempList->lpstr)+1)*sizeof(TCHAR)); else { lpOutputData[0] = (BYTE)0; lpOutputData[1] = (BYTE)0; } lpOutputData += (lstrlen((LPTSTR)lpOutputData)+1)*sizeof(TCHAR); lpTempList = lpTempList->pst_next; } while (lpTempList != NULL);
if (lpOldValueName) { HRESULT hr; //We calculte the buffer for lpVal->lpPre_valuename, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchCopy(lpVal->lpPre_valuename, cbPre_valuename, lpOldValueName); }
lpVal->ve.ve_valuelen = dwOutputSize; lpVal->ve.ve_type = dwType; lpVal->pvl_next = NULL; lpVal->md.dwMDIdentifier = 0x00FFFFFF;
AddNodeToList(lpVal, lpValList); } else hResult = S_OK;
Exit: if (lpStrList) { FreeStrList (lpStrList); }
if(lpNewValueName) { free(lpNewValueName); } return hResult; }
//-----------------------------------------------------------------------
//
// Function: IsAdmin
//
// Descrip: Check whether current user is in administrators group
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes:
//
//-----------------------------------------------------------------------
BOOL IsAdmin() { // get the administrator sid
PSID psidAdministrators; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; BOOL bIsAdmin = FALSE;
if(!AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators)) { return FALSE; }
// on NT5, we should use the CheckTokenMembershipAPI to correctly handle cases where
// the Adiminstrators group might be disabled. bIsAdmin is BOOL for
// CheckTokenMembership checks if the SID is enabled in the token. NULL for
// the token means the token of the current thread. Disabled groups, restricted
// SIDS, and SE_GROUP_USE_FOR_DENY_ONLY are all considered. If the function
// returns false, ignore the result.
if (!CheckTokenMembership(NULL, psidAdministrators, &bIsAdmin)) { bIsAdmin = FALSE; } FreeSid(psidAdministrators); return bIsAdmin; }
//-----------------------------------------------------------------------
//
// Function: DoesUserHavePrivilege
//
// Descrip:
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz copied from NTSETUP
//
// Routine Description:
// This routine returns TRUE if the caller's process has
// the specified privilege. The privilege does not have
// to be currently enabled. This routine is used to indicate
// whether the caller has the potential to enable the privilege.
// Caller is NOT expected to be impersonating anyone and IS
// expected to be able to open their own process and process
// token.
// Arguments:
// Privilege - the name form of privilege ID (such as
// SE_SECURITY_NAME).
//Return Value:
// TRUE - Caller has the specified privilege.
// FALSE - Caller does not have the specified privilege.
BOOL DoesUserHavePrivilege( PTSTR PrivilegeName ) { HANDLE Token; ULONG BytesRequired; PTOKEN_PRIVILEGES Privileges; BOOL b; DWORD i; LUID Luid;
//
// Open the process token.
//
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) { return(FALSE); }
b = FALSE; Privileges = NULL;
//
// Get privilege information.
//
if(!GetTokenInformation(Token,TokenPrivileges,NULL,0,&BytesRequired) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && (Privileges = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR,BytesRequired)) && GetTokenInformation(Token,TokenPrivileges,Privileges,BytesRequired,&BytesRequired) && LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) {
//
// See if we have the requested privilege
//
for(i=0; i<Privileges->PrivilegeCount; i++) {
if(!memcmp(&Luid,&Privileges->Privileges[i].Luid,sizeof(LUID))) {
b = TRUE; break; } } }
//
// Clean up and return.
//
if(Privileges) { LocalFree((HLOCAL)Privileges); }
CloseHandle(Token);
return(b); }
//-----------------------------------------------------------------------
//
// Function: EnablePrivilege
//
// Descrip:
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz copied from NTSETUP
//
// Notes:
//
//-----------------------------------------------------------------------
BOOL EnablePrivilege( IN PTSTR PrivilegeName, IN BOOL Enable ) { HANDLE Token; BOOL b; TOKEN_PRIVILEGES NewPrivileges; LUID Luid;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) { return(FALSE); }
if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) { CloseHandle(Token); return(FALSE); }
NewPrivileges.PrivilegeCount = 1; NewPrivileges.Privileges[0].Luid = Luid; NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
b = AdjustTokenPrivileges( Token, FALSE, &NewPrivileges, 0, NULL, NULL );
CloseHandle(Token);
return(b); } //-----------------------------------------------------------------------
//
// Function: GetCurrentControlSet
//
// Descrip:
//
// Returns: INT
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: the HKLM\SYSTEM\CurrentControlSet is actually is copy of
// HKLM\SYSTEM\ControlSetXXX, the XXX is specified in
// HKLM\SYSTEM\Select\Current . This API returns this XXX,
// if it failed , it returns -1
//
//-----------------------------------------------------------------------
INT GetCurrentControlSet() { DWORD dwErr; DWORD dwCurrrent,dwSize; HKEY hKey = NULL;
dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\Select"), 0, KEY_READ, &hKey );
// if failed to open registry key , return -1
if( dwErr != ERROR_SUCCESS ) { dwCurrrent = -1; hKey = NULL; goto Cleanup; }
dwSize = sizeof(DWORD); dwErr = RegQueryValueEx(hKey, TEXT("Current"), NULL, //reserved
NULL, //type
(LPBYTE) &dwCurrrent, &dwSize );
if(dwErr != ERROR_SUCCESS) { dwCurrrent = -1; goto Cleanup; } //Notes:here we succeeded in geting the value, do we need to do
//a registry open to make sure the actual HKLM\SYSTEM\ControlSetXXX
//is there
Cleanup: if (hKey) { RegCloseKey(hKey); } return dwCurrrent; }
//-----------------------------------------------------------------------
//
// Function: ReplaceCurrentControlSet
//
// Descrip:
//
// Returns: BOOL
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: replace CurrentControlSet with ControlSetXXX
//
//-----------------------------------------------------------------------
HRESULT ReplaceCurrentControlSet(LPTSTR strList) { INT nCurrent; TCHAR szCurrCrtlSet[MAX_PATH]; DWORD dwStrLen; TCHAR *lpTmpBuf; HRESULT hr;
//If the string list is empty .we just return
dwStrLen = MultiSzLen(strList); if (dwStrLen < 3) { return S_OK; }
//If there is no CurrentControlSet in the String list, just return
if (!MultiSzSubStr (TEXT("CurrentControlSet"),strList)) { return S_FALSE; } //Get the CurrentControlSet #, this is specified in registry , detail see GetCurrentControlSet
nCurrent = GetCurrentControlSet();
// if we can not get, just bail out
if (nCurrent < 0) { return HRESULT_FROM_WIN32(GetLastError()); }
//This indeed will never fail, unless this registry value has been tamnpered,
// we will bail out then
if (FAILED(hr = StringCchPrintf(szCurrCrtlSet,MAX_PATH,TEXT("ControlSet%03d\0"),nCurrent))) { return hr; }
//Get a Temp buffer for saving replaced string, dwStrLen already includes the last NULL
// in this multi-sz string
lpTmpBuf = malloc( dwStrLen * sizeof(TCHAR) ); if (!lpTmpBuf) { return E_OUTOFMEMORY; }
memmove((BYTE*)lpTmpBuf,(BYTE*)strList,dwStrLen * sizeof(TCHAR)); hr = StringMultipleReplacement(lpTmpBuf,TEXT("CurrentControlSet\0"),szCurrCrtlSet,strList,dwStrLen); if (FAILED(hr)) { memmove(strList,lpTmpBuf,dwStrLen * sizeof(TCHAR)); } free(lpTmpBuf); return hr; }
//-----------------------------------------------------------------------
//
// Function: UnProtectSFPFiles
//
// Descrip:
//
// Returns: DWORD
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes: Unprotect a list of files specified by multiSzFileList which
// is multi-sz string. pdwResult is an array of DWORD which will
// be specifed whether success or failure of each unprotect action
// if can be NULL if called does not care this information.
// the retuan value is BOOL,if is FALSE, it means starting SFP
// service failed.
//
//-----------------------------------------------------------------------
BOOL UnProtectSFPFiles( IN LPTSTR multiSzFileList, IN OUT LPDWORD pdwResult) { HANDLE hSfp = INVALID_HANDLE_VALUE; DWORD bResult = TRUE; LPTSTR lp; LPDWORD lpdw; DWORD dw;
//If the no string there, we just return success
if (!multiSzFileList) { goto Cleanup; } //Connect to SFP service
hSfp = SfcConnectToServer( NULL ); if (INVALID_HANDLE_VALUE == hSfp) { bResult = FALSE; goto Cleanup; } //lp points to Path while lpdw points to the result array
lp = multiSzFileList; lpdw = pdwResult; while (*lp) { DWORD dwResult = NO_ERROR;
//if the file pointed by lp is in the file protection list
// unprotect it and put the return value to array
if (SfcIsFileProtected(hSfp,lp)) { dwResult = SfcFileException(hSfp,lp, SFC_ACTION_ADDED | SFC_ACTION_REMOVED | SFC_ACTION_MODIFIED | SFC_ACTION_RENAMED_OLD_NAME |SFC_ACTION_RENAMED_NEW_NAME); } else { dw = GetLastError(); } if (lpdw) { *lpdw = dwResult; lpdw++; } lp = lp + lstrlen(lp) + 1; }
Cleanup: if (hSfp) { SfcClose(hSfp); } return bResult; }
/*++
Routine Description:
This routine returns TRUE if the caller's process has the specified privilege. The privilege does not have to be currently enabled. This routine is used to indicate whether the caller has the potential to enable the privilege.
Caller is NOT expected to be impersonating anyone and IS expected to be able to open their own process and process token.
Arguments:
lpDir - the direcory which is to be backuped lpBackupDir - the backup directory name we got , it should be %lpDir%.CLMTxxx - where xxx is 000,001,... cChBackupDir is the lpBackupDir's size in TCHAR bFindExist - if this is TRUE , it means the lpDir has already been backuiped - and caller wants to get that dir name - if this is FALSE , it means the caller want to find an appriate backup - dir name for lpDir Return Value:
TRUE - The directory name found.
FALSE - The directory can not be found --*/
BOOL GetBackupDir( LPCTSTR lpDir, LPTSTR lpBackupDir, size_t cChBackupDir, BOOL bFindExist) { BOOL bResult = FALSE; HRESULT hr; int nCounter; HANDLE hFile; WIN32_FIND_DATA fd;
if (!lpDir && !lpDir[0]) { goto Exit; }
if (!lpBackupDir) { goto Exit; } for (nCounter = 0 ; nCounter < 1000 ; nCounter++) { // Try appending counter after
TCHAR szCounter[10]; _itot(nCounter,szCounter,10); hr = StringCchPrintf(lpBackupDir,cChBackupDir, TEXT("%s.%s%03s"),lpDir,TEXT("clmt"),szCounter); if ( FAILED(hr) ) { goto Exit; }
// Does this directory name exist?
hFile = FindFirstFile(lpBackupDir, &fd);
if (INVALID_HANDLE_VALUE == hFile) { // Directory does not exist, use this one
FindClose(hFile); break; } else { // Directory exists, keep finding...
FindClose(hFile); } }//end of for nCounter
if (nCounter < 1000) { //we found a dir name that does not exist
if (bFindExist) { if (nCounter > 0) { TCHAR szCounter[10]; nCounter--; _itot(nCounter,szCounter,10); hr = StringCchPrintf(lpBackupDir,cChBackupDir, TEXT("%s.%s%03s"),lpDir,TEXT("clmt"),szCounter); if ( FAILED(hr) ) { goto Exit; } } else { goto Exit; } } bResult = TRUE; } Exit: return (bResult);
}
//Add an entry in INF file for key rename
//szOldKeyPath --- the key needs to be renamed
//szNewKeyPath --- to name to be renamed to
//szUsername --- if it's HKLM, HKCR, this needs to be NULL
// ---- otherwise it's the username for registry
HRESULT AddRegKeyRename( LPTSTR lpszKeyRoot, LPTSTR lpszOldKeyname, LPTSTR lpszNewKeyname, LPTSTR szUsername) { TCHAR *lpszOneLine =NULL; TCHAR *lpszSectionName = NULL; DWORD cchOneLine; DWORD cchSectionNameLen; HRESULT hr; TCHAR szIndex[MAX_PATH]; LPTSTR lpUserStringSid = NULL; PSID pSid = NULL; LPTSTR lpszKeyRootWithoutBackSlash = lpszKeyRoot; LPTSTR lpszKeyRootWithoutBackSlash1 = NULL,lpszOldKeyname1 = NULL,lpszNewKeyname1 = NULL;
if ( !lpszKeyRoot || !lpszOldKeyname || !lpszNewKeyname) { hr = E_INVALIDARG; goto Cleanup; } cchOneLine = lstrlen(lpszKeyRoot)+lstrlen(lpszOldKeyname)+lstrlen(lpszNewKeyname)+MAX_PATH; if (szUsername) { cchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); } else { cchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); } lpszOneLine = malloc(cchOneLine*sizeof(TCHAR)); lpszSectionName = malloc(cchSectionNameLen*sizeof(TCHAR));
if (!lpszOneLine || !lpszSectionName) { hr = E_OUTOFMEMORY; goto Cleanup; }
if (lpszKeyRoot[0]==TEXT('\\')) { lpszKeyRootWithoutBackSlash = lpszKeyRoot + 1; } if (!szUsername ||!MyStrCmpI(szUsername,TEXT("System"))) { hr = StringCchCopy(lpszSectionName,cchSectionNameLen,REG_PERSYS_UPDATE); if (FAILED(hr)) { goto Cleanup; } } else { if (!MyStrCmpI(szUsername,DEFAULT_USER) ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE)) { hr = StringCchPrintf(lpszSectionName,cchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,szUsername); if (FAILED(hr)) { goto Cleanup; } } else { hr = GetSIDFromName(szUsername,&pSid); if (FAILED(hr)) { goto Cleanup; } if (!ConvertSidToStringSid(pSid,&lpUserStringSid)) { lpUserStringSid = NULL; hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } if (cchSectionNameLen < (DWORD)(lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX) + lstrlen(REG_PERSYS_UPDATE))) { LPTSTR pTmp; cchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX) + lstrlen(REG_PERSYS_UPDATE); pTmp = realloc(lpszSectionName,cchSectionNameLen*sizeof(TCHAR)); if (!pTmp) { hr = E_OUTOFMEMORY; goto Cleanup; } else { lpszSectionName = pTmp; } } hr = StringCchPrintf(lpszSectionName,cchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,lpUserStringSid); if (FAILED(hr)) { goto Cleanup; } } } AddExtraQuoteEtc(lpszKeyRootWithoutBackSlash,&lpszKeyRootWithoutBackSlash1); AddExtraQuoteEtc(lpszOldKeyname,&lpszOldKeyname1); AddExtraQuoteEtc(lpszNewKeyname,&lpszNewKeyname1);
hr = StringCchPrintf(lpszOneLine,cchOneLine,TEXT("%d,\"%s\",\"%s\",\"%s\""), CONSTANT_REG_KEY_RENAME,lpszKeyRootWithoutBackSlash1, lpszOldKeyname1,lpszNewKeyname1); if (FAILED(hr)) { goto Cleanup; } g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); if (!WritePrivateProfileString(lpszSectionName,szIndex,lpszOneLine,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { hr = S_OK; } Cleanup: FreePointer(lpszOneLine); FreePointer(lpszSectionName); FreePointer(lpszKeyRootWithoutBackSlash1); FreePointer(lpszOldKeyname1); FreePointer(lpszNewKeyname1);
if (lpUserStringSid) { LocalFree(lpUserStringSid); } FreePointer(pSid); return (hr); }
HRESULT SetSectionName ( LPTSTR szUsername, LPTSTR *lpszSectionName) { HRESULT hr; PSID pSid = NULL; LPTSTR lpUserStringSid = NULL; DWORD dwCchSectionNameLen;
if (szUsername) { dwCchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); } else { dwCchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); }
*lpszSectionName = malloc(dwCchSectionNameLen*sizeof(TCHAR)); if (!*lpszSectionName) { hr = E_OUTOFMEMORY; goto Cleanup; } if (!szUsername ||!MyStrCmpI(szUsername,TEXT("System"))) { //We calculte the buffer for lpszSectionName, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchCopy(*lpszSectionName,dwCchSectionNameLen,REG_PERSYS_UPDATE); } else { if (!MyStrCmpI(szUsername,DEFAULT_USER) ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE)) { hr = StringCchPrintf(*lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,szUsername); if (FAILED(hr)) { goto Cleanup; } } else { LPTSTR pTmp; hr = GetSIDFromName(szUsername,&pSid); if (FAILED(hr)) { goto Cleanup; } if (!ConvertSidToStringSid(pSid,&lpUserStringSid)) { lpUserStringSid = NULL; hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } dwCchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); pTmp = realloc(*lpszSectionName,dwCchSectionNameLen*sizeof(TCHAR)); if (!pTmp) { hr = E_OUTOFMEMORY; goto Cleanup; } else { *lpszSectionName = pTmp; } hr = StringCchPrintf(*lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,lpUserStringSid); if (FAILED(hr)) { goto Cleanup; } } }
Cleanup: if (lpUserStringSid) { LocalFree(lpUserStringSid); } if (FAILED(hr)) FreePointer(*lpszSectionName);
FreePointer(pSid); return hr; }
//Add an entry in INF file for Value rename
//szKeyPath: Key path
//szOldValueName: Old value name
//szNewValueName: New value name. Set to NULL if value name is not changed.
//szOldValueData: Old value data. Set to NULL if value data is not changed.
//szNewValueData: New value data. Set to NULL if value data is not changed.
//dwType: Date type REG_SZ,REG_EXPAND_SZ,REG_MULTI_SZ
//dwAttrib: Value string attribute
//szUsername: If it's HKLM, HKCR, this needs to be NULL
// otherwise it's the username for registry
HRESULT AddRegValueRename( LPTSTR szKeyPath, LPTSTR szOldValueName, LPTSTR szNewValueName, LPTSTR szOldValueData, LPTSTR szNewValueData, DWORD dwType, DWORD dwAttrib, LPTSTR szUsername) { HRESULT hr; TCHAR *szRenameValueDataLine = NULL; TCHAR *szRenameValueNameLine = NULL; DWORD dwCchsizeforRenameValueData; DWORD dwCchsizeforRenameValueName = MAX_PATH ; TCHAR *lpszSectionName = NULL; DWORD dwCchSectionNameLen; TCHAR szIndex[MAX_PATH]; LPTSTR lpUserStringSid = NULL; PSID pSid = NULL; LPTSTR lpszKeyPathWithoutBackSlash = NULL,lpszKeyPathWithoutBackSlash1 = NULL; LPTSTR lpszOldNameWithExtraQuote = NULL, lpszNewNameWithExtraQuote = NULL; LPTSTR lpszValueDataExtraQuote = NULL;
if (szUsername) { dwCchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); } else { dwCchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); }
lpszSectionName = malloc(dwCchSectionNameLen*sizeof(TCHAR)); if (!lpszSectionName) { hr = E_OUTOFMEMORY; goto Cleanup; } if (!szUsername ||!MyStrCmpI(szUsername,TEXT("System"))) { lpszKeyPathWithoutBackSlash = szKeyPath; //We calculte the buffer for lpszSectionName, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchCopy(lpszSectionName,dwCchSectionNameLen,REG_PERSYS_UPDATE); } else { if (szKeyPath[0]==TEXT('\\')) { lpszKeyPathWithoutBackSlash = szKeyPath + 1; } else { lpszKeyPathWithoutBackSlash = szKeyPath; } if (!MyStrCmpI(szUsername,DEFAULT_USER) ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE)) { hr = StringCchPrintf(lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,szUsername); if (FAILED(hr)) { goto Cleanup; } } else { LPTSTR pTmp; hr = GetSIDFromName(szUsername,&pSid); if (FAILED(hr)) { goto Cleanup; } if (!ConvertSidToStringSid(pSid,&lpUserStringSid)) { lpUserStringSid = NULL; hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } dwCchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE); pTmp = realloc(lpszSectionName,dwCchSectionNameLen*sizeof(TCHAR)); if (!pTmp) { hr = E_OUTOFMEMORY; goto Cleanup; } else { lpszSectionName = pTmp; } hr = StringCchPrintf(lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"), REG_PERUSER_UPDATE_PREFIX,lpUserStringSid); if (FAILED(hr)) { goto Cleanup; } } } hr = AddExtraQuoteEtc(lpszKeyPathWithoutBackSlash,&lpszKeyPathWithoutBackSlash1); if (FAILED(hr)) { goto Cleanup; } hr = AddExtraQuoteEtc(szOldValueName,&lpszOldNameWithExtraQuote); if (FAILED(hr)) { goto Cleanup; }
if (szNewValueData) { if ((dwType & 0xffff) == REG_MULTI_SZ) { LPTSTR lpString = NULL; hr = MultiSZ2String(szNewValueData,TEXT(','),&lpString); if (FAILED(hr)) { goto Cleanup; } dwCchsizeforRenameValueData = lstrlen(lpszKeyPathWithoutBackSlash1) + lstrlen(szOldValueName) + lstrlen(lpString) + MAX_PATH; szRenameValueDataLine = malloc(dwCchsizeforRenameValueData*sizeof(TCHAR)); if (!szRenameValueDataLine) { hr = E_OUTOFMEMORY; FreePointer(lpString); goto Cleanup; } hr = StringCchPrintf(szRenameValueDataLine,dwCchsizeforRenameValueData, TEXT("%d,%d,\"%s\",\"%s\",%s"),CONSTANT_REG_VALUE_DATA_RENAME, dwType,lpszKeyPathWithoutBackSlash1,szOldValueName,lpString); FreePointer(lpString); if (FAILED(hr)) { goto Cleanup; } } else { hr = AddExtraQuoteEtc(szNewValueData,&lpszValueDataExtraQuote); if (FAILED(hr)) { goto Cleanup; } dwCchsizeforRenameValueData = lstrlen(lpszKeyPathWithoutBackSlash1) + lstrlen(szOldValueName) + lstrlen(lpszValueDataExtraQuote) + MAX_PATH; szRenameValueDataLine = malloc(dwCchsizeforRenameValueData*sizeof(TCHAR)); if (!szRenameValueDataLine) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = StringCchPrintf(szRenameValueDataLine,dwCchsizeforRenameValueData, TEXT("%d,%u,\"%s\",\"%s\",\"%s\""), CONSTANT_REG_VALUE_DATA_RENAME, dwType,lpszKeyPathWithoutBackSlash1,lpszOldNameWithExtraQuote, lpszValueDataExtraQuote); if (FAILED(hr)) { goto Cleanup; } } g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); if (!WritePrivateProfileString(lpszSectionName,szIndex,szRenameValueDataLine,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } } if (szNewValueName) { hr = AddExtraQuoteEtc(szNewValueName,&lpszNewNameWithExtraQuote); if (FAILED(hr)) { goto Cleanup; } dwCchsizeforRenameValueName = lstrlen(lpszKeyPathWithoutBackSlash1) + lstrlen(lpszOldNameWithExtraQuote) + lstrlen(lpszNewNameWithExtraQuote) + MAX_PATH; szRenameValueNameLine = malloc(dwCchsizeforRenameValueName*sizeof(TCHAR)); if (!szRenameValueNameLine) { hr = E_OUTOFMEMORY; goto Cleanup; }
hr = StringCchPrintf(szRenameValueNameLine,dwCchsizeforRenameValueName,TEXT("%d,\"%s\",\"%s\",\"%s\""), CONSTANT_REG_VALUE_NAME_RENAME,lpszKeyPathWithoutBackSlash1, lpszOldNameWithExtraQuote,lpszNewNameWithExtraQuote); if (FAILED(hr)) { goto Cleanup; } g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); if (!WritePrivateProfileString(lpszSectionName,szIndex,szRenameValueNameLine,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } } hr = S_OK; Cleanup: if (lpUserStringSid) { LocalFree(lpUserStringSid); } FreePointer(lpszOldNameWithExtraQuote); FreePointer(lpszNewNameWithExtraQuote); FreePointer(lpszValueDataExtraQuote); FreePointer(szRenameValueDataLine); FreePointer(szRenameValueNameLine); FreePointer(lpszSectionName); FreePointer(pSid); FreePointer(lpszKeyPathWithoutBackSlash1); return (hr); }
HRESULT AddFolderRename( LPTSTR szOldName, LPTSTR szNewName, DWORD dwType, LPTSTR lpExcludeList) { LPTSTR szSectionName = TEXT("Folder.ObjectRename"); LPTSTR szOneLine = NULL; size_t CchOneLine = MAX_PATH; TCHAR szIndex[MAX_PATH]; HRESULT hr; LPTSTR lpString = NULL;
switch (dwType) { case TYPE_DIR_MOVE: if (lpExcludeList) { hr = MultiSZ2String(lpExcludeList,TEXT(','),&lpString); if (FAILED(hr)) { goto Cleanup; } CchOneLine +=lstrlen(lpString)+lstrlen(szOldName)+lstrlen(szNewName); szOneLine = malloc(CchOneLine * sizeof(TCHAR)); if (!szOneLine) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%d,\"%s\",\"%s\",%s"), dwType,szOldName,szNewName,lpString); free(lpString); if (FAILED(hr)) { goto Cleanup; } break; }
else { } case TYPE_SFPFILE_MOVE: case TYPE_FILE_MOVE: CchOneLine += lstrlen(szOldName)+lstrlen(szNewName); szOneLine = malloc(CchOneLine * sizeof(TCHAR)); if (!szOneLine) { hr = E_OUTOFMEMORY; goto Cleanup; } hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%d,\"%s\",\"%s\""),dwType,szOldName,szNewName); if (FAILED(hr)) { goto Cleanup; } break; } g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); if (!WritePrivateProfileString(szSectionName,szIndex,szOneLine,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; }
// Add the file/folder rename to Change log
// Does not care about return value
hr = AddFileChangeLog(dwType, szOldName, szNewName);
hr = S_OK; Cleanup: if (szOneLine) { free(szOneLine); } if (lpString) { free(lpString); } return hr;
}
LONG EnsureCLMTReg() { HKEY hkey = NULL; LONG lStatus;
lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey); if (lStatus == ERROR_SUCCESS) { RegCloseKey(hkey); } return lStatus; }
HRESULT SaveInstallLocale(void) { HKEY hkey = NULL; LONG lStatus; HRESULT hr; LCID lcid; TCHAR szLocale[MAX_PATH]; TCHAR szStr[16];
lcid = GetInstallLocale(); if (!lcid) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (!IsValidLocale(lcid,LCID_INSTALLED)) { hr = E_FAIL; goto Exit; } _itot(lcid,szStr,16); //StringCchCopy should be always success, since we called IsValidLocale to make sure
//it is a valid locale which should be less than MAX_PATH chars
hr = StringCchPrintf(szLocale,ARRAYSIZE(szLocale),TEXT("%08s"),szStr);
lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey); if (lStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } lStatus = RegSetValueEx(hkey, CLMT_OriginalInstallLocale, 0, //reserved
REG_SZ,//type
(LPBYTE) szLocale, (lstrlen(szLocale)+1)*sizeof(TCHAR)); if( lStatus != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } hr = S_OK; Exit: if (hkey) { RegCloseKey(hkey); } return hr; }
HRESULT GetSavedInstallLocale(LCID *plcid) { HKEY hkey = NULL; LONG lStatus; HRESULT hr; LCID lcid; TCHAR szLocale[MAX_PATH]; TCHAR *pStop; DWORD dwSize;
if ( !plcid ) { hr = E_INVALIDARG; goto Exit; } lStatus = RegOpenKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey); if (lStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } dwSize = MAX_PATH *sizeof(TCHAR); lStatus = RegQueryValueEx(hkey, CLMT_OriginalInstallLocale, NULL, //reserved
NULL,//type
(LPBYTE) szLocale, &dwSize); if( lStatus != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } *plcid = _tcstol(szLocale, &pStop, 16); if (!IsValidLocale(*plcid,LCID_INSTALLED)) { hr = E_FAIL; goto Exit; } hr = S_OK; Exit: if (hkey) { RegCloseKey(hkey); } return hr; }
HRESULT SetCLMTStatus(DWORD dwRunStatus) { HKEY hkey = NULL; LONG lStatus; HRESULT hr;
if ( (dwRunStatus != CLMT_DOMIG) && (dwRunStatus != CLMT_UNDO_PROGRAM_FILES) && (dwRunStatus != CLMT_UNDO_APPLICATION_DATA) && (dwRunStatus != CLMT_UNDO_ALL) && (dwRunStatus != CLMT_DOMIG_DONE) && (dwRunStatus != CLMT_UNDO_PROGRAM_FILES_DONE) && (dwRunStatus != CLMT_UNDO_APPLICATION_DATA_DONE) && (dwRunStatus != CLMT_UNDO_ALL_DONE) && (dwRunStatus != CLMT_CURE_PROGRAM_FILES) && (dwRunStatus != CLMT_CLEANUP_AFTER_UPGRADE) ) { hr = E_INVALIDARG; goto Exit; }
lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey); if (lStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; }
lStatus = RegSetValueEx(hkey, CLMT_RUNNING_STATUS, 0, //reserved
REG_DWORD,//type
(LPBYTE) &dwRunStatus, sizeof(DWORD)); if( lStatus != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } hr = S_OK; Exit: if (hkey) { RegCloseKey(hkey); } return hr; }
HRESULT GetCLMTStatus(PDWORD pdwRunStatus) { HKEY hkey = NULL; LONG lStatus; HRESULT hr; DWORD dwSize;
if ( !pdwRunStatus ) { hr = E_INVALIDARG; goto Exit; }
lStatus = RegOpenKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey); if (lStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; }
dwSize = sizeof(DWORD); lStatus = RegQueryValueEx(hkey, CLMT_RUNNING_STATUS, NULL, NULL, (LPBYTE)pdwRunStatus, &dwSize); if( lStatus != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(lStatus); goto Exit; } hr = S_OK; Exit: if (hkey) { RegCloseKey(hkey); } return hr; }
//-----------------------------------------------------------------------
//
// Function: GetInstallLocale
//
// Descrip: Get the OS installed locale
//
// Returns: LCID
//
// Notes: if fails, the return value is 0, otherwize is the os 's lcid
//
// History: 09/17/2001 xiaoz created
//
// Notes: If it returns 0, it means failure, and call GetLastError() to get the detail
// error code
//
//-----------------------------------------------------------------------
UINT GetInstallLocale(VOID) { LONG dwErr; HKEY hkey; DWORD dwSize; TCHAR buffer[512]; LANGID rcLang; UINT lcid;
lcid = 0; dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\Language"), 0, KEY_READ, &hkey );
if( dwErr == ERROR_SUCCESS ) {
dwSize = sizeof(buffer); dwErr = RegQueryValueEx(hkey, TEXT("InstallLanguage"), NULL, //reserved
NULL, //type
(LPBYTE) buffer, &dwSize );
if(dwErr == ERROR_SUCCESS) { lcid = StrToUInt(buffer); } RegCloseKey(hkey); } return( lcid ); }
//-----------------------------------------------------------------------
//
// Function: SetInstallLocale
//
// Descrip: Set the OS installed locale
//
// Returns: HRESULT
//
// Notes:
//
// History: 09/17/2001 xiaoz created
//
//
//-----------------------------------------------------------------------
HRESULT SetInstallLocale(LCID lcid) { LONG dwErr; HKEY hkey = NULL; TCHAR szLocale[32],szTmpLocale[32]; HRESULT hr;
if (!IsValidLocale(lcid,LCID_INSTALLED)) { hr = E_INVALIDARG; goto Exit; } dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\Language"), 0, KEY_WRITE, &hkey );
if( dwErr != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(dwErr); goto Exit; } //following 2 sentences should never fail since we already validated by IsValidLocale
_itot(lcid,szTmpLocale,16);
//StringCchCopy should be always success, since we called IsValidLocale to make sure
//it is a valid locale which should be less than 32 chars
hr = StringCchPrintf(szLocale,ARRAYSIZE(szLocale),TEXT("%04s"),szTmpLocale);
dwErr = RegSetValueEx(hkey, TEXT("InstallLanguage"), 0, //reserved
REG_SZ,//type
(LPBYTE) szLocale, (lstrlen(szLocale)+1)*sizeof(TCHAR)); if( dwErr != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(dwErr); goto Exit; }
hr = S_OK; Exit: if (hkey) { RegCloseKey(hkey); } return hr; }
//
// Function: ReverseStrCmp
//
// Description: Reverse compare strings
//
// Returns: TRUE if two strings are equal.
// FALSE if different.
// Notes:
//
// History: 3/14/2002 geoffguo created
//
BOOL ReverseStrCmp( LPCTSTR lpCurrentChar, LPCTSTR lpStrBuf) { BOOL bRet = FALSE; DWORD i, dwLen; LPCTSTR lpStr1, lpStr2;
if (!lpCurrentChar || !lpStrBuf) goto Exit;
dwLen = lstrlen(lpStrBuf); do { bRet = TRUE; lpStr1 = lpCurrentChar; lpStr2 = &lpStrBuf[dwLen-1]; for (i = 0; i < dwLen; i++) { if (IsBadStringPtr(lpStr1, 1) || *lpStr1 == (TCHAR)'\0' || towupper(*lpStr1) != towupper(*lpStr2) && *lpStr2 != L':' && //solve MS Installer path issue: G?\Program Files
*lpStr2 != L'\\') //solve MS FrontPage URL format issue: D:/Document and Settings
{ bRet = FALSE; break; } lpStr1--; lpStr2--; }
if (bRet) break;
dwLen--; } while (lpStrBuf[dwLen-1] != (TCHAR)'\\' && dwLen > 0);
Exit: return bRet; }
DWORD MultiSZNumOfString(IN LPTSTR lpMultiSZ) { DWORD dwNum = 0; LPTSTR lpStr = lpMultiSZ; if (!lpMultiSZ) { return 0; } while (*lpStr) { dwNum++; lpStr = lpStr + lstrlen(lpStr)+1; } return dwNum;
}
//
// Function: StrNumInMultiSZ
//
// Description: Get string number in multi-string
//
// Returns: String number or 0xFFFFFFFF if not find.
//
// Notes:
//
// History: 3/21/2002 geoffguo created
//
DWORD StrNumInMultiSZ( LPCTSTR lpStr, LPCTSTR lpMultiSZ) { DWORD dwNum = 0xFFFFFFFF; LPTSTR lpTemp; if (!lpMultiSZ || !lpStr) { goto Exit; } lpTemp = (LPTSTR)lpMultiSZ; dwNum = 0; while (*lpTemp) { if(MyStrCmpI(lpStr, lpTemp) == 0) break;
dwNum++; lpTemp = lpTemp + lstrlen(lpTemp)+1; }
if (*lpTemp == (TCHAR)NULL) dwNum = 0xFFFFFFFF;
Exit: return dwNum; }
//
// Function: GetStrInMultiSZ
//
// Description: Get string in multi-string based on string number.
//
// Returns: Point to the string or NULL.
//
// Notes:
//
// History: 3/21/2002 geoffguo created
//
LPTSTR GetStrInMultiSZ( DWORD dwNum, LPCTSTR lpMultiSZ) { DWORD i; LPTSTR lpTemp = NULL; if (!lpMultiSZ) { goto Exit; } lpTemp = (LPTSTR)lpMultiSZ; i = 0; while (*lpTemp) { if(i == dwNum) break;
i++; lpTemp = lpTemp + lstrlen(lpTemp)+1; }
if (*lpTemp == (TCHAR)NULL) lpTemp = NULL;
Exit: return lpTemp; }
HRESULT MultiSZ2String( IN LPTSTR lpMultiSZ, IN TCHAR chSeperator, OUT LPTSTR *lpString) { LPTSTR lpSource = NULL,lpDest = NULL,lpDestStart = NULL,lpTmpBuf = NULL; DWORD cchLen ; HRESULT hr; DWORD dwNumofStringInMSZ;
if (!lpMultiSZ || !lpString ) { hr = E_INVALIDARG; goto Cleanup; } cchLen = MultiSzLen(lpMultiSZ); if (cchLen < 3) { hr = E_INVALIDARG; *lpString = NULL; goto Cleanup; }
dwNumofStringInMSZ = MultiSZNumOfString(lpMultiSZ);
lpDest = malloc( (cchLen + dwNumofStringInMSZ * 2) * sizeof(TCHAR)); lpDestStart = lpDest; lpTmpBuf = malloc( (cchLen + dwNumofStringInMSZ * 2) * sizeof(TCHAR)); if (!lpDest || !lpTmpBuf) { hr = E_OUTOFMEMORY; goto Cleanup; }
lpSource = lpMultiSZ; while (*lpSource) { //We calculte the buffer for lpTmpBuf, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchPrintf(lpTmpBuf,cchLen + dwNumofStringInMSZ * 2,TEXT("\"%s\""),lpSource); memcpy((BYTE*)lpDest,(BYTE*)lpTmpBuf,lstrlen(lpTmpBuf) * sizeof(TCHAR)); lpSource = lpSource + lstrlen(lpSource)+1; lpDest = lpDest + lstrlen(lpTmpBuf); *lpDest = chSeperator; lpDest++; } lpDest--; *lpDest = TEXT('\0'); hr = S_OK; Cleanup: if (lpTmpBuf) { free(lpTmpBuf); } if FAILED(hr) { if (lpDestStart) { free(lpDestStart); } lpDestStart = NULL; } *lpString = lpDestStart; return hr; }
void FreePointer(void *lp) { if (lp) { free(lp); } }
HRESULT GetSIDFromName( IN LPTSTR lpszUserName, OUT PSID *ppSid) { PSID pSid = NULL; DWORD cbSid = 1024; SID_NAME_USE Use ; HRESULT hr; DWORD dwDomainNameLen = MAX_PATH; TCHAR szDomain[MAX_PATH];
if (!lpszUserName) { hr = E_INVALIDARG; goto Cleanup; } pSid = (PSID)malloc( cbSid); if(!pSid) { hr = E_OUTOFMEMORY; goto Cleanup; } if (LookupAccountName(NULL,lpszUserName,pSid,&cbSid,szDomain,&dwDomainNameLen,&Use)== FALSE) { DWORD dwErr = GetLastError(); if(dwErr != ERROR_INSUFFICIENT_BUFFER) { hr = HRESULT_FROM_WIN32(dwErr); goto Cleanup; } else { free(pSid); pSid = (PSID)malloc( cbSid); if(!pSid) { hr = E_OUTOFMEMORY; goto Cleanup; } dwDomainNameLen = MAX_PATH; if (LookupAccountName(NULL,lpszUserName,pSid,&cbSid,szDomain,&dwDomainNameLen,&Use)== FALSE) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Cleanup; } } } //Check the SID
if(!IsValidSid(pSid)) { hr = E_FAIL; goto Cleanup; } hr = S_OK; Cleanup: if FAILED(hr) { if (pSid) { free(pSid); } *ppSid = NULL; } else { *ppSid = pSid; } return hr; }
void BoostMyPriority() { HANDLE hProcess;
hProcess = GetCurrentProcess(); SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS); }
//***************************************************************************
//
// BOOL StopService
//
// DESCRIPTION:
//
// Stops and then removes the service.
//
// PARAMETERS:
//
// pServiceName short service name
// dwMaxWait max time in seconds to wait
//
// RETURN VALUE:
//
// TRUE if it worked
//
//***************************************************************************
BOOL StopService( IN LPCTSTR pServiceName, IN DWORD dwMaxWait) { BOOL bRet = FALSE; SC_HANDLE schService; SC_HANDLE schSCManager; DWORD dwCnt; SERVICE_STATUS ssStatus; // current status of the service
schSCManager = OpenSCManager( NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
); if ( schSCManager ) { schService = OpenService(schSCManager, pServiceName, SERVICE_ALL_ACCESS);
if (schService) { // try to stop the service
if ( bRet = ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) { for(dwCnt=0; dwCnt < dwMaxWait && QueryServiceStatus( schService, &ssStatus ); dwCnt++) { if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) Sleep( 1000 ); else break; }
}
CloseServiceHandle(schService); }
CloseServiceHandle(schSCManager); } return bRet; }
//***************************************************************************
//
// HRESULT ReconfigureServiceStartType
//
// DESCRIPTION:
//
// Change the Service Start Type, there are following type availabe now
// SERVICE_AUTO_START
// SERVICE_BOOT_START
// SERVICE_DEMAND_START
// SERVICE_DISABLED
// SERVICE_SYSTEM_START
//
// PARAMETERS:
//
// pServiceName short service name
// dwOldType service current start type
// dwNewType start type you want to change to
// dwMaxWait max time in seconds to wait
//
// RETURN VALUE: S_OK if change successfully
//
// Note: if current start type is dwOldType, the function will try to
// change start type to dwNewType.
// if current start type is NOT dwOldType, it will not do any
// change, in this S_FALSE is returned.
// If you want change service start type to dwNewType, no mater
// current start type, specify dwOldType >=0xFFFF
//
//***************************************************************************
HRESULT ReconfigureServiceStartType( IN LPCTSTR pServiceName, IN DWORD dwOldType, IN DWORD dwNewType, IN DWORD dwMaxWait) { SC_LOCK sclLock = NULL; SERVICE_DESCRIPTION sdBuf; DWORD dwBytesNeeded, dwStartType; SC_HANDLE schSCManager = NULL; SC_HANDLE schService = NULL; DWORD dwErr = ERROR_SUCCESS; LPQUERY_SERVICE_CONFIG lpqscBuf = NULL; HRESULT hr = S_OK; DWORD dwCnt;
schSCManager = OpenSCManager( NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
); if (!schSCManager) { dwErr = GetLastError(); goto cleanup; } // Need to acquire database lock before reconfiguring.
for(dwCnt=0; dwCnt < dwMaxWait ; dwCnt++) { sclLock = LockServiceDatabase(schSCManager); if (sclLock == NULL) { // Exit if the database is not locked by another process.
dwErr = GetLastError(); if (dwErr != ERROR_SERVICE_DATABASE_LOCKED) { goto cleanup; } else { Sleep(1000); } } else { break; } } if (!sclLock) { goto cleanup; } // The database is locked, so it is safe to make changes.
// Open a handle to the service.
schService = OpenService( schSCManager, // SCManager database
pServiceName, // name of service
SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG ); // need CHANGE access
if (schService == NULL) { dwErr = GetLastError(); goto cleanup; } lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096); if (lpqscBuf == NULL) { dwErr = ERROR_OUTOFMEMORY; goto cleanup; }
if (!QueryServiceConfig(schService, // handle to service
lpqscBuf, // buffer
4096, // size of buffer
&dwBytesNeeded)) { dwErr = GetLastError(); goto cleanup; } if (dwOldType < 0xFFFF) { if (lpqscBuf->dwStartType != dwOldType) { hr = S_FALSE; goto cleanup; } } // Make the changes.
if (! ChangeServiceConfig(schService, // handle of service
SERVICE_NO_CHANGE, // service type: no change
dwNewType, // change service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL) ) // display name: no change
{ dwErr = GetLastError(); goto cleanup; }
hr = S_OK; cleanup: if (dwErr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwErr); } if (sclLock) { UnlockServiceDatabase(sclLock); } if (schService) { // Close the handle to the service.
CloseServiceHandle(schService); } if (schSCManager) { CloseServiceHandle(schSCManager); } if (lpqscBuf) { LocalFree(lpqscBuf); } return hr; }
//-----------------------------------------------------------------------
//
// Function: MyGetShortPathName
//
// Descrip:
//
// Returns: DWORD
//
// Notes: none
//
// History: 09/17/2001 xiaoz created
//
// Notes:
// lpszLongPath is the long path name
// lpszOriginalPath (optional)is the the original name of lpszLongPath(before we renamed it)
// lpszShortPath is the buffer to receive the short path name
// cchBuffer is the buffer size for lpszShortPath
//
//-----------------------------------------------------------------------
#define BYTE_COUNT_8_DOT_3 (24)
HRESULT MyGetShortPathName( IN LPCTSTR lpszPathRoot, IN LPCTSTR lpszOldName, IN LPCTSTR lpszNewName, OUT LPTSTR lpszShortName, IN DWORD cchBuffer) { HRESULT hr = S_OK; GENERATE_NAME_CONTEXT NameContext; WCHAR ShortNameBuffer[BYTE_COUNT_8_DOT_3 / sizeof( WCHAR ) + 1]; UNICODE_STRING FileName,ShortName; DWORD StringLength; LPTSTR lpName; TCHAR szPath[MAX_PATH],szLongPath[MAX_PATH]; TCHAR DriveRoot[_MAX_DRIVE + 2]; #define FILESYSNAMEBUFSIZE 1024 // probably more than we need
TCHAR szFileSystemType[FILESYSNAMEBUFSIZE]; BOOL bIsNTFS = FALSE; BOOL bTmpDirCreated = FALSE; DWORD dwAllowExtendedChar; BOOLEAN bAllowExtendedChar; DWORD dwsizeofdw;
if (lstrlen(lpszNewName) <= 8) { hr = StringCchCopy(lpszShortName,cchBuffer,lpszNewName); goto Exit; } //
// Initialize the short string to use the input buffer.
//
ShortName.Buffer = ShortNameBuffer; ShortName.MaximumLength = BYTE_COUNT_8_DOT_3; FileName.Buffer = (LPTSTR)lpszNewName; StringLength = lstrlen(lpszNewName); FileName.Length = (USHORT)StringLength * sizeof(TCHAR); FileName.MaximumLength = (USHORT)(StringLength + 1)*sizeof(TCHAR);
// Initialize the name context.
//
RtlZeroMemory( &NameContext, sizeof( GENERATE_NAME_CONTEXT )); #define EXTENDED_CHAR_MODE_VALUE_NAME TEXT("NtfsAllowExtendedCharacterIn8dot3Name")
#define COMPATIBILITY_MODE_KEY_NAME TEXT("System\\CurrentControlSet\\Control\\FileSystem")
dwsizeofdw = sizeof(DWORD); if (ERROR_SUCCESS == GetRegistryValue(HKEY_LOCAL_MACHINE, COMPATIBILITY_MODE_KEY_NAME, EXTENDED_CHAR_MODE_VALUE_NAME, (LPBYTE)&dwAllowExtendedChar, &dwsizeofdw)) { if (dwAllowExtendedChar) { bAllowExtendedChar = TRUE; } else { bAllowExtendedChar = FALSE; } } else { bAllowExtendedChar = FALSE; } RtlGenerate8dot3Name( &FileName, bAllowExtendedChar, &NameContext, &ShortName );
//now ShortName.Buffer contains the shortpath and is NULL ended
ShortName.Buffer[ShortName.Length /sizeof(TCHAR)] = TEXT('\0'); //check whether the short name is exitsted or now
hr = StringCchCopy(szPath,ARRAYSIZE(szPath),lpszPathRoot); if (FAILED(hr)) { goto Exit; } if (!ConcatenatePaths(szPath,ShortName.Buffer,ARRAYSIZE(szPath))) { hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); goto Exit; } if (!IsFileFolderExisting(szPath)) { hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer); goto Exit; } _tsplitpath(lpszPathRoot, DriveRoot, NULL, NULL, NULL); hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\")); if (FAILED(hr)) { hr = E_INVALIDARG; goto Exit; }
if (! GetVolumeInformation(DriveRoot, NULL, 0, NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) ) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (!MyStrCmpI(szFileSystemType,TEXT("NTFS"))) { bIsNTFS = TRUE; } //Follwing we process the short name path is existing.
if (!GetLongPathName(szPath,szLongPath,ARRAYSIZE(szLongPath))) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } lpName = StrRChrI(szLongPath,NULL,TEXT('\\')); if (!lpName) { hr = E_FAIL; goto Exit; } if (!MyStrCmpI(lpName+1,lpszOldName)) { if (bIsNTFS) { hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer); goto Exit; } } else if (!MyStrCmpI(lpName,lpszNewName)) { hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer); goto Exit; }
//here we need to get the shortpath name by creating it
hr = StringCchCopy(szLongPath,ARRAYSIZE(szLongPath),lpszPathRoot); if (FAILED(hr)) { goto Exit; } if (!ConcatenatePaths(szLongPath,lpszNewName,ARRAYSIZE(szLongPath))) { hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); goto Exit; } if (!CreateDirectory(szLongPath,NULL)) { DWORD dwErr = GetLastError(); if (dwErr != ERROR_ALREADY_EXISTS) { hr = HRESULT_FROM_WIN32(dwErr); goto Exit; } } else { bTmpDirCreated = TRUE; }
if (!GetShortPathName(szLongPath,szPath,cchBuffer)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (bTmpDirCreated) { RemoveDirectory(szLongPath); } if (!(lpName = StrRChrI(szPath,NULL,TEXT('\\')))) { hr = E_FAIL; goto Exit; } hr = StringCchCopy(lpszShortName,cchBuffer,lpName+1); Exit: return hr; }
BOOL MassageLinkValue( IN LPCWSTR lpLinkName, IN LPCWSTR lpLinkValue, OUT PUNICODE_STRING NtLinkName, OUT PUNICODE_STRING NtLinkValue, OUT PUNICODE_STRING DosLinkValue ) { PWSTR FilePart; PWSTR s, sBegin, sBackupLimit, sLinkName; NTSTATUS Status; USHORT nSaveNtNameLength; ULONG nLevels;
//
// Initialize output variables to NULL
//
RtlInitUnicodeString( NtLinkName, NULL ); RtlInitUnicodeString( NtLinkValue, NULL );
//
// Translate link name into full NT path.
//
if (!RtlDosPathNameToNtPathName_U( lpLinkName, NtLinkName, &sLinkName, NULL ) ) { return FALSE; }
//
// All done if no link value.
//
if (!ARGUMENT_PRESENT( lpLinkValue )) { return TRUE; }
//
// If the target is a device, do not allow the link.
//
if (RtlIsDosDeviceName_U( (PWSTR)lpLinkValue )) { return FALSE; }
//
// Convert to DOS path to full path, and get Nt representation
// of DOS path.
//
if (!RtlGetFullPathName_U( lpLinkValue, DosLinkValue->MaximumLength, DosLinkValue->Buffer, NULL ) ) { return FALSE; } DosLinkValue->Length = wcslen( DosLinkValue->Buffer ) * sizeof( WCHAR );
//
// Verify that the link value is a valid NT name.
//
if (!RtlDosPathNameToNtPathName_U( DosLinkValue->Buffer, NtLinkValue, NULL, NULL ) ) { return FALSE; }
return TRUE; } // MassageLinkValue
BOOL CreateSymbolicLink( LPTSTR szLinkName, LPTSTR szLinkValue, BOOL bMakeLinkHidden ) {
NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle;
UNICODE_STRING UnicodeName; UNICODE_STRING NtLinkName; UNICODE_STRING NtLinkValue; UNICODE_STRING DosLinkValue;
WCHAR FullPathLinkValue[ DOS_MAX_PATH_LENGTH+1 ];
IO_STATUS_BLOCK IoStatusBlock; BOOL TranslationStatus;
PVOID FreeBuffer; PVOID FreeBuffer2;
FILE_DISPOSITION_INFORMATION Disposition;
PREPARSE_DATA_BUFFER ReparseBufferHeader = NULL; PCHAR ReparseBuffer = NULL; ULONG ReparsePointTag = IO_REPARSE_TAG_RESERVED_ZERO; USHORT ReparseDataLength = 0;
ULONG FsControlCode = 0; ULONG CreateOptions = 0; ULONG CreateDisposition = 0; ULONG DesiredAccess = SYNCHRONIZE; DWORD dwAttrib; BOOL bRet = FALSE;
// change the name to NT path, eg d:\programme to ??\d:\programme
TranslationStatus = RtlDosPathNameToNtPathName_U( szLinkName, &UnicodeName, NULL, NULL );
if (!TranslationStatus) { goto exit; }
FreeBuffer = UnicodeName.Buffer;
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL );
//
// Set the code of the FSCTL operation.
//
FsControlCode = FSCTL_SET_REPARSE_POINT;
//
// Set the open/create options for a directory.
//
CreateOptions = FILE_OPEN_REPARSE_POINT;
//
// Set the tag to mount point.
//
ReparsePointTag = IO_REPARSE_TAG_MOUNT_POINT;
//
// Open to set the reparse point.
//
DesiredAccess |= FILE_WRITE_DATA; CreateDisposition = FILE_OPEN; // the file must be present
Status = NtCreateFile(&Handle, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, // pallocationsize (none!)
FILE_ATTRIBUTE_NORMAL,// attributes to be set if created
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, CreateDisposition, CreateOptions, NULL, // EA buffer (none!)
0);
//
// Create a directory if you do not find it.
//
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { DesiredAccess = SYNCHRONIZE; CreateDisposition = FILE_CREATE; CreateOptions = FILE_DIRECTORY_FILE;
Status = NtCreateFile(&Handle, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, // pallocationsize (none!)
FILE_ATTRIBUTE_NORMAL, // attributes to be set if created
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, CreateDisposition, CreateOptions, NULL, // EA buffer (none!)
0); if (!NT_SUCCESS(Status)) { goto exit; }
//
// Close the handle and re-open.
//
NtClose( Handle );
CreateOptions = FILE_OPEN_REPARSE_POINT; DesiredAccess |= FILE_WRITE_DATA; CreateDisposition = FILE_OPEN; // the file must be present
Status = NtCreateFile(&Handle, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, // pallocationsize (none!)
FILE_ATTRIBUTE_NORMAL, // attributes to be set if created
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, CreateDisposition, CreateOptions, NULL, // EA buffer (none!)
0); } RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer ); if (!NT_SUCCESS(Status)) { goto exit; } //
// Innitialize the DosName buffer.
//
DosLinkValue.Buffer = FullPathLinkValue; DosLinkValue.MaximumLength = sizeof( FullPathLinkValue ); DosLinkValue.Length = 0;
//
// Massage all the names.
//
if (!MassageLinkValue( szLinkName, szLinkValue, &NtLinkName, &NtLinkValue, &DosLinkValue )) { RtlFreeUnicodeString( &NtLinkName ); RtlFreeUnicodeString( &NtLinkValue ); goto exit; } RtlFreeUnicodeString( &NtLinkName );
//
// Set the reparse point with mount point or symbolic link tag and determine
// the appropriate length of the buffer.
//
ReparseDataLength = (USHORT)((FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - REPARSE_DATA_BUFFER_HEADER_SIZE) + NtLinkValue.Length + sizeof(UNICODE_NULL) + DosLinkValue.Length + sizeof(UNICODE_NULL));
//
// Allocate a buffer to set the reparse point.
//
ReparseBufferHeader = (PREPARSE_DATA_BUFFER)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
if (ReparseBufferHeader == NULL) { NtClose( Handle ); RtlFreeUnicodeString( &NtLinkValue ); goto exit; }
//
// Setting the buffer is common for both tags as their buffers have identical fields.
//
ReparseBufferHeader->ReparseDataLength = (USHORT)ReparseDataLength; ReparseBufferHeader->Reserved = 0; ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameLength = NtLinkValue.Length; ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameOffset = NtLinkValue.Length + sizeof( UNICODE_NULL ); ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameLength = DosLinkValue.Length; RtlCopyMemory(ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer, NtLinkValue.Buffer, NtLinkValue.Length); RtlCopyMemory((PCHAR)(ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer)+ NtLinkValue.Length + sizeof(UNICODE_NULL), DosLinkValue.Buffer, DosLinkValue.Length);
RtlFreeUnicodeString( &NtLinkValue ); //
// Set the tag
//
ReparseBufferHeader->ReparseTag = ReparsePointTag;
//
// Set the reparse point.
//
Status = NtFsControlFile(Handle, NULL, NULL, NULL, &IoStatusBlock, FsControlCode, ReparseBufferHeader, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseBufferHeader->ReparseDataLength, NULL, // no output buffer
0); // output buffer length\
//
// Close the file.
//
NtClose( Handle );
if (!NT_SUCCESS(Status)) { goto exit; } bRet = TRUE; if (bMakeLinkHidden) { dwAttrib = GetFileAttributes(szLinkName); if (INVALID_FILE_ATTRIBUTES == dwAttrib) { goto exit; } if (!SetFileAttributes(szLinkName,dwAttrib|FILE_ATTRIBUTE_HIDDEN)) { DPF (APPmsg, L"SetFileAttributes! Error: %d \n", GetLastError()); goto exit; } } exit: return bRet; }
BOOL GetSymbolicLink( LPTSTR szLinkName, LPTSTR szLinkValue, DWORD cchSize ) {
NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle;
UNICODE_STRING UnicodeName; UNICODE_STRING NtLinkName; UNICODE_STRING NtLinkValue; UNICODE_STRING DosLinkValue;
WCHAR FullPathLinkValue[ DOS_MAX_PATH_LENGTH+1 ];
IO_STATUS_BLOCK IoStatusBlock; BOOL TranslationStatus;
PVOID FreeBuffer; PVOID FreeBuffer2;
FILE_DISPOSITION_INFORMATION Disposition;
PREPARSE_DATA_BUFFER ReparseBufferHeader = NULL; PCHAR ReparseBuffer = NULL; ULONG ReparsePointTag = IO_REPARSE_TAG_RESERVED_ZERO; USHORT ReparseDataLength = 0;
ULONG FsControlCode = 0; ULONG CreateOptions = 0; ULONG CreateDisposition = 0; ULONG DesiredAccess = SYNCHRONIZE; DWORD dwAttrib; BOOL bRet = FALSE;
// change the name to NT path, eg d:\programme to ??\d:\programme
TranslationStatus = RtlDosPathNameToNtPathName_U( szLinkName, &UnicodeName, NULL, NULL );
if (!TranslationStatus) { goto exit; }
FreeBuffer = UnicodeName.Buffer;
InitializeObjectAttributes( &ObjectAttributes, &UnicodeName, OBJ_CASE_INSENSITIVE, NULL, NULL );
FsControlCode = FSCTL_GET_REPARSE_POINT; DesiredAccess = FILE_READ_DATA | SYNCHRONIZE; CreateOptions = FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT; //
// Set the tag to mount point.
//
ReparsePointTag = IO_REPARSE_TAG_MOUNT_POINT;
Status = NtOpenFile( &Handle, DesiredAccess, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, CreateOptions );
RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
if (!NT_SUCCESS(Status)) { goto exit; } ReparseDataLength = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; ReparseBuffer = RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, ReparseDataLength );
if (ReparseBuffer == NULL) { goto exit; } Status = NtFsControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, FsControlCode, // no input buffer
NULL, // input buffer length
0, (PVOID)ReparseBuffer, ReparseDataLength ); if (!NT_SUCCESS(Status)) { NtClose( Handle ); RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader ); goto exit; }
NtClose( Handle ); ReparseBufferHeader = (PREPARSE_DATA_BUFFER)ReparseBuffer; if ((ReparseBufferHeader->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) || (ReparseBufferHeader->ReparseTag == IO_REPARSE_TAG_SYMBOLIC_LINK)) {
USHORT Offset = 0; NtLinkValue.Buffer = &ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer[Offset]; NtLinkValue.Length = ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameLength; Offset = NtLinkValue.Length + sizeof(UNICODE_NULL); DosLinkValue.Buffer = &ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer[Offset/sizeof(WCHAR)]; DosLinkValue.Length = ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameLength; if (cchSize < DosLinkValue.Length / sizeof(TCHAR) +1) { RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader ); goto exit; } else { int cbLen = DosLinkValue.Length; LPTSTR lpStart = DosLinkValue.Buffer;
if (DosLinkValue.Length > 4 * sizeof(TCHAR)) { if ( (DosLinkValue.Buffer[0] == TEXT('\\')) && (DosLinkValue.Buffer[1] == TEXT('\\')) && (DosLinkValue.Buffer[2] == TEXT('?')) && (DosLinkValue.Buffer[3] == TEXT('\\')) ) { cbLen -= 4 * sizeof(TCHAR); lpStart += 4; } } //memmove((PBYTE)szLinkValue,(PBYTE)DosLinkValue.Buffer,DosLinkValue.Length);
//szLinkValue[DosLinkValue.Length / sizeof(TCHAR)] = TEXT('\0');
memmove((PBYTE)szLinkValue,(PBYTE)lpStart,cbLen); szLinkValue[cbLen / sizeof(TCHAR)] = TEXT('\0'); } } else { RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader ); goto exit; }
bRet = TRUE; RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader ); exit: return bRet; }
typedef struct { WORD wSuiteMask; LPTSTR szSuiteName; } SUITE_INFO;
HRESULT LogMachineInfo() { SYSTEMTIME systime; OSVERSIONINFOEX ov; TCHAR lpTimeStr[MAX_PATH]; TCHAR lpComputerName[MAX_COMPUTERNAME_LENGTH + 1]; SUITE_INFO c_rgSuite_Info[] = { {VER_SUITE_BACKOFFICE, TEXT("Microsoft BackOffice")}, {VER_SUITE_BLADE, TEXT("Windows Server 2003, Web Edition")}, {VER_SUITE_DATACENTER, TEXT("Datacenter Server")}, {VER_SUITE_ENTERPRISE, TEXT("Advanced/Enterprise Server")}, {VER_SUITE_PERSONAL, TEXT("Windows XP Home Edition")}, {VER_SUITE_SMALLBUSINESS, TEXT("Small Business Server")}, {VER_SUITE_SMALLBUSINESS_RESTRICTED, TEXT("Restricted Small Business Server")}, {VER_SUITE_TERMINAL, TEXT("Terminal Services")}, {0,NULL} }; SUITE_INFO *psi; LCID lcidSys,lcidUser,lcidInstall; TCHAR szLocalename[MAX_PATH]; TCHAR szSystemDir[MAX_PATH+1]; #define FILESYSNAMEBUFSIZE 1024 // probably more than we need
TCHAR szFileSystemType[FILESYSNAMEBUFSIZE]; DWORD cchSize; TCHAR szModule[MAX_PATH+1]; TCHAR szCurrRoot[MAX_PATH+1],szExpRoot[MAX_PATH+1]; DWORD cchCurrRoot,cchExpRoot; HRESULT hr = S_OK;
if (GetModuleFileName(GetModuleHandle(NULL),szModule,ARRAYSIZE(szModule)-1)) { szModule[ARRAYSIZE(szModule)-1] = TEXT('\0'); DPF(APPmsg, TEXT("CLMT Version: %s started from %s"),TEXT(VER_FILEVERSION_STR),szModule); } else { DPF(APPmsg, TEXT("CLMT Version: %s"),TEXT(VER_FILEVERSION_STR)); } GetSystemTime(&systime); if (GetTimeFormat(LOCALE_USER_DEFAULT,0,&systime,NULL,lpTimeStr,ARRAYSIZE(lpTimeStr))) { DPF(APPmsg, TEXT("CLMT started at %s,%d/%d/%d"),lpTimeStr,systime.wMonth,systime.wDay ,systime.wYear ); }
cchSize = ARRAYSIZE(lpComputerName); if (GetComputerName(lpComputerName,&cchSize)) { DPF(APPmsg, TEXT("Computer name : %s"),lpComputerName); } ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (GetVersionEx((LPOSVERSIONINFO)&ov)) { TCHAR szProductType[MAX_PATH]; TCHAR szSuiteList[MAX_PATH]; DPF(APPmsg, TEXT("OS Version: %d.%d"),ov.dwMajorVersion,ov.dwMinorVersion); if (ov.szCSDVersion[0]) { DPF(APPmsg, TEXT("Service Pack: %s"),ov.szCSDVersion); } switch (ov.wProductType ) { case VER_NT_WORKSTATION: hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("NT_WORKSTATION")); break; case VER_NT_DOMAIN_CONTROLLER: hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("DOMAIN_CONTROLLER")); break; case VER_NT_SERVER : hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("NT_SERVER")); break; default: hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("Unknow Type")); } if (FAILED(hr)) { return hr; } DPF(APPmsg, TEXT("Product Type: %s"),szProductType); szSuiteList[0] = TEXT('\0'); for (psi = c_rgSuite_Info; psi->szSuiteName; psi++) { if (psi->wSuiteMask & ov.wSuiteMask) { hr = StringCchCat(szSuiteList,ARRAYSIZE(szSuiteList),psi->szSuiteName); if (FAILED(hr)) { break; } } } if (FAILED(hr)) { return hr; } if (szSuiteList[0]) { DPF(APPmsg, TEXT("Suite List: %s"),szSuiteList); } } lcidSys = GetSystemDefaultLCID(); lcidUser = GetUserDefaultLCID(); lcidInstall = GetInstallLocale(); if (GetLocaleInfo(lcidInstall,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename))) { DPF(APPmsg, TEXT("OS LanguageID/Name: %x,%s"),lcidInstall,szLocalename); } else { DPF(APPmsg, TEXT("OS LanguageID/Name: %x"),lcidInstall); }
if (GetLocaleInfo(lcidSys,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename))) { DPF(APPmsg, TEXT("System locale ID/Name: %x,%s"),lcidSys,szLocalename); } else { DPF(APPmsg, TEXT("System locale ID: %x"),lcidSys); } if (GetLocaleInfo(lcidUser,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename))) { DPF(APPmsg, TEXT("User Locale ID/Name: %x,%s"),lcidUser,szLocalename); } else { DPF(APPmsg, TEXT("User Locale ID: %x"),lcidUser); } if (GetSystemDirectory(szSystemDir, ARRAYSIZE(szSystemDir))) { TCHAR DriveRoot[_MAX_DRIVE + 2]; ULARGE_INTEGER FreeBytesAvailable; // bytes available to caller
ULARGE_INTEGER TotalNumberOfBytes; // bytes on disk
ULARGE_INTEGER TotalNumberOfFreeBytes;
DPF(APPmsg, TEXT("System Dir is : %s"),szSystemDir); _tsplitpath(szSystemDir, DriveRoot, NULL, NULL, NULL); if (FAILED(hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\")))) { return hr; } if ( GetVolumeInformation(DriveRoot, NULL, 0, NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) ) { DPF(APPmsg, TEXT("System Drive File System is : %s"),szFileSystemType); } if (GetDiskFreeSpaceEx(szSystemDir,&FreeBytesAvailable,&TotalNumberOfBytes,&TotalNumberOfFreeBytes)) { TCHAR szFreeBytesAvailable[64],szTotalNumberOfBytes[64],szTotalNumberOfFreeBytes[64]; _ui64tot(FreeBytesAvailable.QuadPart,szFreeBytesAvailable,10); _ui64tot(TotalNumberOfBytes.QuadPart,szTotalNumberOfBytes,10); _ui64tot(TotalNumberOfFreeBytes.QuadPart,szTotalNumberOfFreeBytes,10); DPF(APPmsg, TEXT("Free Space Available for system drive : %s"),szFreeBytesAvailable); DPF(APPmsg, TEXT("Total Space Available for system drive : %s"),szTotalNumberOfBytes); DPF(APPmsg, TEXT("Total Free Space Available for system drive : %s"),szTotalNumberOfFreeBytes);
} } cchCurrRoot = ARRAYSIZE(szCurrRoot); cchExpRoot = ARRAYSIZE(szExpRoot); if ( (GetRegistryValue(HKEY_LOCAL_MACHINE,TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"), TEXT("PathName"),(LPBYTE)szExpRoot,&cchExpRoot)==ERROR_SUCCESS) && (GetRegistryValue(HKEY_LOCAL_MACHINE,TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"), TEXT("SystemRoot"),(LPBYTE)szCurrRoot,&cchCurrRoot)==ERROR_SUCCESS) ) { szExpRoot[1] = TEXT('\0'); szCurrRoot[1] = TEXT('\0'); if (MyStrCmpI(szExpRoot,szCurrRoot)) { DPF(APPmsg, TEXT("Warning : System Drive is not correct, supposed to be ---%s Drive---, right now is --- %s Drive ---"),szExpRoot,szCurrRoot); DPF(APPmsg, TEXT("Warning : This is usually caused by you ghost the image from one partition, and recover to another")); } } return S_OK; } HRESULT AddExtraQuoteEtc( LPTSTR lpszStrIn, LPTSTR *lplpszStrOut) { LPTSTR lpStart,lpAtSpecialChar,lpDest; DWORD cchSpechialCharCount = 0,cchStrLen; HRESULT hr; LPTSTR szSpecialStrList[] = {TEXT("\""),TEXT("%%"),NULL}; int i , nCurrSpecialStr; TCHAR szTemplate[MAX_PATH]; if (!lpszStrIn || !lplpszStrOut) { return E_INVALIDARG; } i = 0; while (szSpecialStrList[i]) { lpStart = lpszStrIn; while (lpAtSpecialChar = StrStrI(lpStart,szSpecialStrList[i])) { cchSpechialCharCount += lstrlen(szSpecialStrList[i]); lpStart = lpAtSpecialChar + lstrlen(szSpecialStrList[i]); } i++; } if (!cchSpechialCharCount) { *lplpszStrOut = malloc ( (lstrlen(lpszStrIn) +1) * sizeof(TCHAR)); if (!*lplpszStrOut) { return E_OUTOFMEMORY; } hr = StringCchCopy(*lplpszStrOut,lstrlen(lpszStrIn) +1,lpszStrIn); return S_FALSE; } cchStrLen = lstrlen(lpszStrIn) + cchSpechialCharCount + 1; *lplpszStrOut = malloc (cchStrLen * sizeof(TCHAR)); if (!*lplpszStrOut) { return E_OUTOFMEMORY; } hr = StringCchCopy(*lplpszStrOut,cchStrLen,TEXT(""));
lpStart = lpszStrIn; lpAtSpecialChar = lpszStrIn;
while (*lpStart) { LPTSTR lp1stSpecialChar = NULL;
nCurrSpecialStr = 0; for (i = 0; szSpecialStrList[i]; i++) { lpAtSpecialChar = StrStrI(lpStart,szSpecialStrList[i]); if (lpAtSpecialChar && !lp1stSpecialChar) { lp1stSpecialChar = lpAtSpecialChar; nCurrSpecialStr = i; } else if (lpAtSpecialChar && lp1stSpecialChar) { if (lpAtSpecialChar < lp1stSpecialChar) { lp1stSpecialChar = lpAtSpecialChar; nCurrSpecialStr = i; } } } if (lp1stSpecialChar) { TCHAR chTmp = *lp1stSpecialChar; *lp1stSpecialChar = TEXT('\0');
hr = StringCchCat(*lplpszStrOut,cchStrLen,lpStart); *lp1stSpecialChar = chTmp; for (i = 0; i< lstrlen(szSpecialStrList[nCurrSpecialStr])* 2; i++) { szTemplate[i] = chTmp; } szTemplate[i] = TEXT('\0'); hr = StringCchCat(*lplpszStrOut,cchStrLen,szTemplate); lpStart = lp1stSpecialChar + lstrlen(szSpecialStrList[nCurrSpecialStr]); } else { hr = StringCchCat(*lplpszStrOut,cchStrLen,lpStart); lpStart = lpStart + lstrlen(lpStart); } } return S_OK; }
HRESULT CopyMyselfTo(LPTSTR lpszDestDir) { TCHAR szModule[2*MAX_PATH+1]; LPTSTR lpszNewFile,lpFileName; DWORD cchLen; BOOL bCopied; HRESULT hr;
if (!lpszDestDir || !lpszDestDir[0]) { return E_INVALIDARG; } if (!GetModuleFileName(GetModuleHandle(NULL),szModule,ARRAYSIZE(szModule)-1)) { szModule[ARRAYSIZE(szModule)-1] = TEXT('\0'); return HRESULT_FROM_WIN32(GetLastError()); } lpFileName = StrRChrIW(szModule,NULL,TEXT('\\')); if (!lpFileName) { return E_FAIL; } lpFileName++; if (! *lpFileName) { return E_FAIL; } cchLen = lstrlen(lpszDestDir)+ lstrlen(lpFileName) + 2; // one for "\\", one for ending NULL
if (!(lpszNewFile = malloc(cchLen * sizeof(TCHAR)))) { return E_OUTOFMEMORY; } //We calculte the buffer for lpszNewFile, so here StringCchCopy should be
//always success, assinging return value just make prefast happy
hr = StringCchCopy(lpszNewFile,cchLen,lpszDestDir); ConcatenatePaths(lpszNewFile,lpFileName,cchLen); bCopied = CopyFile(szModule,lpszNewFile,FALSE); if (bCopied) { free(lpszNewFile); return S_OK; } else { DWORD dw = GetLastError(); DWORD dwAttrib = GetFileAttributes(lpszNewFile);
if ( (dwAttrib & FILE_ATTRIBUTE_READONLY) ||(dwAttrib & FILE_ATTRIBUTE_SYSTEM) ) { if (SetFileAttributes(lpszNewFile,FILE_ATTRIBUTE_NORMAL)) { bCopied = CopyFile(szModule,lpszNewFile,FALSE); if (bCopied) { dw = ERROR_SUCCESS; } else { dw = GetLastError(); } } } free(lpszNewFile); return HRESULT_FROM_WIN32(dw); } }
// local functions
HRESULT SetRunOnceValue ( IN LPCTSTR szValueName, IN LPCTSTR szValue) { HKEY hRunOnceKey = NULL; DWORD dwStatus = ERROR_SUCCESS; DWORD cbData; const TCHAR* szRunOnceKeyPath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"); if (NULL == szValueName || TEXT('\0') == szValueName[0]) { dwStatus = ERROR_INVALID_PARAMETER; goto SetRunOnceValueEnd; } if (NULL == szValue || TEXT('\0') == szValue[0]) { dwStatus = ERROR_INVALID_PARAMETER; goto SetRunOnceValueEnd; } dwStatus = RegOpenKey (HKEY_LOCAL_MACHINE, szRunOnceKeyPath, &hRunOnceKey); if (ERROR_SUCCESS != dwStatus) { goto SetRunOnceValueEnd; } cbData = ( lstrlen(szValue) + 1) * sizeof(TCHAR); dwStatus = RegSetValueEx (hRunOnceKey, szValueName, 0, // Reserved
REG_SZ, (CONST BYTE *) szValue, cbData);
SetRunOnceValueEnd: if (hRunOnceKey) { RegCloseKey(hRunOnceKey); } return HRESULT_FROM_WIN32(dwStatus); }
//-----------------------------------------------------------------------
//
// Function: SetRunValue
//
// Descrip:
//
// Returns: BOOL
//
// Notes: none
//
// History:
//
// Notes:
//
//-----------------------------------------------------------------------
HRESULT SetRunValue( LPCTSTR szValueName, LPCTSTR szValue ) { HKEY hRunKey = NULL; DWORD dwStatus = ERROR_SUCCESS; DWORD cbData;
if (NULL == szValueName || TEXT('\0') == szValueName[0] || NULL == szValue || TEXT('\0') == szValue[0]) { return E_INVALIDARG; }
dwStatus = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT_RUN_KEY, &hRunKey); if (ERROR_SUCCESS == dwStatus) { cbData = (lstrlen(szValue) + 1) * sizeof(TCHAR); dwStatus = RegSetValueEx(hRunKey, szValueName, 0, REG_SZ, (CONST BYTE *) szValue, cbData); RegCloseKey(hRunKey); }
return (HRESULT_FROM_WIN32(dwStatus)); }
/*************************************************************
* * CreateSd(void) * Creates a SECURITY_DESCRIPTOR for administrators group. * * NOTES: * Caller must free the returned buffer if not NULL. * * RETURN CODES: * *************************************************************/ HRESULT CreateAdminsSd( PSECURITY_DESCRIPTOR *ppSD) { SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; PSID BuiltInAdministrators = NULL; PSECURITY_DESCRIPTOR Sd = NULL; ULONG AclSize; ACL *Acl; HRESULT hr;
if( ! AllocateAndInitializeSid( &sia, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &BuiltInAdministrators )) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } //
// Calculate the size of and allocate a buffer for the DACL, we need
// this value independently of the total alloc size for ACL init.
//
//
// "- sizeof (ULONG)" represents the SidStart field of the
// ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
// SID, this field is counted twice.
// See detail in InitializeAcl in MSDN
AclSize = sizeof (ACL) + (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG)) + GetLengthSid(BuiltInAdministrators) ;
Sd = LocalAlloc(LMEM_FIXED + LMEM_ZEROINIT, SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
if (!Sd) { hr = E_OUTOFMEMORY; goto Exit; }
Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeAcl(Acl, AclSize, ACL_REVISION)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } //#define ACCESS_ALL GENERIC_ALL | STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL
if (!AddAccessAllowedAce(Acl, ACL_REVISION, //GENERIC_READ | GENERIC_WRITE,
GENERIC_ALL, BuiltInAdministrators)) { // Failed to build the ACE granting "Built-in Administrators"
// STANDARD_RIGHTS_ALL access.
hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
if (!InitializeSecurityDescriptor(Sd,SECURITY_DESCRIPTOR_REVISION)) { // error
hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
if (!SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } *ppSD = Sd; hr = S_OK;
Exit: /* A jump of last resort */ if (hr != S_OK) { *ppSD = NULL; if (Sd) { LocalFree(Sd); } // error
} if (BuiltInAdministrators) { FreeSid(BuiltInAdministrators); } return hr; }
/*************************************************************
* * MyStrCmpIA/W * Do locale independent string comparison(case-insensive) * * NOTES: * It's just a wrapper for CompareString with LOCALE_INVARIANT * we can not use LOCALE_INVARIANT since this is XP+ only * * RETURN CODES: see lstrcmpi in MSDN * *************************************************************/ int MyStrCmpIW( LPCWSTR lpString1, LPCWSTR lpString2) { return ( CompareStringW(LOCALE_ENGLISH, NORM_IGNORECASE, lpString1, -1, lpString2, -1) - 2); }
int MyStrCmpIA( LPCSTR lpString1, LPCSTR lpString2) { return ( CompareStringA(LOCALE_ENGLISH, NORM_IGNORECASE, lpString1, -1, lpString2, -1) - 2); }
//-----------------------------------------------------------------------
//
// Function: MergeDirectory
//
// Descrip: Merge the contents inside source directory to destination
// directory. If file/folder in source dir does not exist in
// destination dir, we will add it to CLMTDO.inf. These files
// or folders will be moved in DoCriticalWork().
//
// Returns: S_OK if function succeeded.
// S_FALSE if source directory does not exist
// else if error occured
//
// Notes: none
//
// History: 04/30/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------
HRESULT MergeDirectory( LPCTSTR lpSrcDir, LPCTSTR lpDstDir ) { HRESULT hr = S_OK; BOOL bRet; WIN32_FIND_DATA FindFileData; HANDLE hFile; TCHAR szDstFile[MAX_PATH]; TCHAR szSrcFile[MAX_PATH]; TCHAR szSearchPath[MAX_PATH];
if (!IsDirExisting((LPTSTR) lpSrcDir)) { return S_FALSE; }
// Destination directory does not exist, no need to do a merge
if (!IsDirExisting((LPTSTR) lpDstDir)) { hr = AddFolderRename((LPTSTR)lpSrcDir, (LPTSTR)lpDstDir, TYPE_DIR_MOVE, NULL); return hr; }
hr = StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), lpSrcDir); if (SUCCEEDED(hr)) { bRet = ConcatenatePaths(szSearchPath, TEXT("*"), ARRAYSIZE(szSearchPath)); if (!bRet) { hr = E_UNEXPECTED; return hr; } } else { return hr; }
//
// Check all files and subdirectores under Source directory
// Merge contents to destination directory as appropriate
//
hFile = FindFirstFileEx(szSearchPath, FindExInfoStandard, &FindFileData, FindExSearchLimitToDirectories, NULL, 0); if (hFile != INVALID_HANDLE_VALUE) { while (SUCCEEDED(hr)) { // Ignore "." and ".." folders
if (lstrcmp(FindFileData.cFileName, TEXT(".")) != LSTR_EQUAL && lstrcmp(FindFileData.cFileName, TEXT("..")) != LSTR_EQUAL) { hr = StringCchCopy(szDstFile, ARRAYSIZE(szDstFile), lpDstDir) || StringCchCopy(szSrcFile, ARRAYSIZE(szSrcFile), lpSrcDir); if (FAILED(hr)) { break; }
bRet = ConcatenatePaths(szDstFile, FindFileData.cFileName, ARRAYSIZE(szDstFile)) && ConcatenatePaths(szSrcFile, FindFileData.cFileName, ARRAYSIZE(szSrcFile)); if (!bRet) { hr = E_UNEXPECTED; break; }
//
// Check if the file is a directory or not
//
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // The file is a directory, do a recursive call
// to merge contents inside it
hr = MergeDirectory(szSrcFile, szDstFile); if (FAILED(hr)) { break; } } else { // This is just a file, move the file to destination folder
// if file does not exist in destination folder
if (!IsFileFolderExisting(szDstFile)) { hr = AddFolderRename(szSrcFile, szDstFile, TYPE_FILE_MOVE, NULL); if (FAILED(hr)) { break; } } } }
// Get the next file in source directory
bRet = FindNextFile(hFile, &FindFileData); if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); } }
FindClose(hFile);
if (HRESULT_CODE(hr) == ERROR_NO_MORE_FILES) { // No more files in source directory, function succeeded
hr = S_OK; } } else { hr = HRESULT_FROM_WIN32(GetLastError()); }
return hr; }
HRESULT IsNTFS( IN LPTSTR lpszPathRoot, OUT BOOL *pbIsNTFS) { TCHAR DriveRoot[_MAX_DRIVE + 2]; BOOL bIsNTFS = FALSE; TCHAR szFileSystemType[FILESYSNAMEBUFSIZE]; HRESULT hr = S_OK;
_tsplitpath(lpszPathRoot, DriveRoot, NULL, NULL, NULL); if (!pbIsNTFS || !lpszPathRoot || !lpszPathRoot[0]) { hr = E_INVALIDARG; goto Exit; } hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\")); if (FAILED(hr)) { hr = E_INVALIDARG; goto Exit; }
if (! GetVolumeInformation(DriveRoot, NULL, 0, NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) ) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (!MyStrCmpI(szFileSystemType,TEXT("NTFS"))) { bIsNTFS = TRUE; } *pbIsNTFS = bIsNTFS;
Exit: return hr; }
HRESULT IsSysVolNTFS(OUT BOOL *pbIsNTFS) { TCHAR szWindir[MAX_PATH+1]; if (!GetSystemWindowsDirectory(szWindir, ARRAYSIZE(szWindir))) { return (HRESULT_FROM_WIN32(GetLastError())); } return IsNTFS(szWindir,pbIsNTFS);
}
BOOL CALLBACK DoCriticalDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HWND hButton1, hButton2, hProgress, hText,hOK, hAdminText; static TCHAR szOK[64], szSTART[64],szCANCEL[64],szCRITICALUPDATING[MAX_PATH], szREMIND_DO_CRITICAL[1024],szREBOOTING[MAX_PATH], szAdminChange[512]; static DWORD dwTimerProgressDone = 10000, dwTimerTickIncrement = 500 , dwTimerTicks; static UINT_PTR dwTimer; TCHAR szOldAdminName[MAX_PATH]; int nRet; BOOL bRet; HRESULT hr; static BOOL bSysUpdated;
#define ID_TIMER 1
switch (uMsg) { case WM_INITDIALOG: // Init the dialog
ShowWindow(hwndDlg, SW_SHOWNORMAL);
dwTimerTicks = 0;
bSysUpdated = FALSE; LoadString(g_hInstDll,IDS_OK,szOK,ARRAYSIZE(szOK)); LoadString(g_hInstDll,IDS_START,szSTART,ARRAYSIZE(szSTART)); LoadString(g_hInstDll,IDS_CANCEL,szCANCEL,ARRAYSIZE(szCANCEL)); LoadString(g_hInstDll,IDS_REMIND_DO_CRITICAL,szREMIND_DO_CRITICAL, ARRAYSIZE(szREMIND_DO_CRITICAL)); LoadString(g_hInstDll,IDS_CRITICALUPDATING,szCRITICALUPDATING, ARRAYSIZE(szCRITICALUPDATING)); LoadString(g_hInstDll,IDS_REBOOTING,szREBOOTING,ARRAYSIZE(szREBOOTING)); hButton1 = GetDlgItem(hwndDlg, ID_BUTTON_1); hButton2 = GetDlgItem(hwndDlg, ID_BUTTON_2); hProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); hText = GetDlgItem(hwndDlg, IDC_STATIC); hOK = GetDlgItem(hwndDlg, IDOK);
ShowWindow(hProgress,SW_HIDE); ShowWindow(hOK,SW_HIDE); SetWindowText(hButton1,szSTART); SetWindowText(hButton2,szCANCEL); SetWindowText(hText,szREMIND_DO_CRITICAL);
SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, dwTimerProgressDone )); SetForegroundWindow(hwndDlg); break;
case WM_COMMAND: // Handle command buttons
switch (wParam) { case ID_BUTTON_1: if (bSysUpdated) { break; } bSysUpdated = TRUE; SetWindowText(hText,szCRITICALUPDATING); ShowWindow(hButton1,SW_HIDE); ShowWindow(hButton2,SW_HIDE); hr = DoCriticalWork(); if (SUCCEEDED(hr)) { bSysUpdated = TRUE; ShowWindow(hOK,SW_SHOW); SetFocus(hOK); DefDlgProc(hwndDlg,DM_SETDEFID, IDOK, 0); dwTimer = SetTimer(hwndDlg,ID_TIMER,dwTimerTickIncrement,NULL); if (dwTimer) { ShowWindow(hProgress,SW_SHOW); SetWindowText(hText,szREBOOTING); } } break;
case ID_BUTTON_2: nRet = DoMessageBox(GetConsoleWindow(), IDS_CONFIRM, IDS_MAIN_TITLE, MB_YESNO|MB_SYSTEMMODAL); if (IDYES == nRet) { EndDialog(hwndDlg, ID_BUTTON_2); } break; case IDOK: if (bSysUpdated) { EndDialog(hwndDlg, ID_UPDATE_DONE); } else { EndDialog(hwndDlg, IDOK); } break; case ID_UPDATE_DONE: EndDialog(hwndDlg, ID_UPDATE_DONE); break; } break; case WM_TIMER: dwTimerTicks += dwTimerTickIncrement; if (dwTimerTicks > dwTimerProgressDone) { KillTimer(hwndDlg, dwTimer); PostMessage(hwndDlg, WM_COMMAND, ID_UPDATE_DONE, 0); } SendMessage(hProgress, PBM_SETPOS,dwTimerTicks,0); break;
case WM_CLOSE: EndDialog(hwndDlg, IDCANCEL); break; default: break; }
return FALSE; }
HRESULT DoCriticalWork () { #ifdef CONSOLE_UI
wprintf(TEXT("updating system settings, !!! Do not Interrupt......\n")); #endif
DPF(APPmsg, TEXT("Enter DoCriticalWork:")); BoostMyPriority(); MakeDOInfCopy(); g_hInfDoItem = SetupOpenInfFile(g_szToDoINFFileName, NULL, INF_STYLE_WIN4, NULL); if (g_hInfDoItem != INVALID_HANDLE_VALUE) { Remove16bitFEDrivers(); ResetServicesStatus(g_hInfDoItem, TEXT_SERVICE_STATUS_SECTION); ResetServicesStartUp(g_hInfDoItem, TEXT_SERVICE_STARTUP_SECTION); // ReconfigureServices(g_hInf);
BatchUpateIISMetabase(g_hInfDoItem,TEXT("Reg.Update.$MetaBase")); BatchFixPathInLink(g_hInfDoItem,TEXT("LNK")); BatchINFUpdate(g_hInfDoItem); FolderMove(g_hInfDoItem,TEXT("Folder.ObjectRename"),FALSE); LoopUser(FinalUpdateRegForUser); // The EnumUserProfile() will be enable after RC 1
// EnumUserProfile(ResetMiscProfilePathPerUser);
UsrGrpAndDoc_and_SettingsRename(g_hInfDoItem,FALSE); UpdateDSObjProp(g_hInfDoItem,DS_OBJ_PROPERTY_UPDATE); INFCreateHardLink(g_hInfDoItem,FOLDER_UPDATE_HARDLINK,FALSE); SetInstallLocale(0x0409); SetProtectedRenamesFlag(TRUE); RegUpdate(g_hInfDoItem, NULL , TEXT("")); SetupCloseInfFile(g_hInfDoItem); DPF(APPmsg, TEXT("Leaving DoCriticalWork:")); return S_OK; } DPF(APPmsg, TEXT("Leaving DoCriticalWork:")); return HRESULT_FROM_WIN32( GetLastError() ); }
HRESULT RenameRegRoot ( LPCTSTR lpSrcStr, LPTSTR lpDstStr, DWORD dwSize, LPCTSTR lpUserSid, LPCTSTR lpKeyName) { HRESULT hResult; TCHAR szKeyBuf[2*MAX_PATH]; TCHAR cNonChar = TEXT('\xFFFF');
if (StrStrI(lpSrcStr, TEXT("HKLM"))) ReplaceString(lpSrcStr,TEXT("HKLM"),TEXT("MACHINE"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE); else if (StrStrI(lpSrcStr, TEXT("HKCR"))) ReplaceString(lpSrcStr,TEXT("HKCR"),TEXT("CLASSES_ROOT"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE); else if (StrStrI(lpSrcStr, TEXT("HKCU"))) ReplaceString(lpSrcStr,TEXT("HKCU"),TEXT("CURRENT_USER"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE); else hResult = StringCchPrintf(szKeyBuf, 2*MAX_PATH, TEXT("USERS\\%s%s"), lpUserSid, lpSrcStr);
if (lpKeyName) hResult = StringCchPrintf(lpDstStr, dwSize, TEXT("%s\\%s"), szKeyBuf, lpKeyName); else hResult = StringCchCopy(lpDstStr, dwSize, szKeyBuf);
return hResult; }
DWORD AdjustRegSecurity ( HKEY hRootKey, LPCTSTR lpSubKeyName, // Registry sub key path
LPCTSTR lpszUsersid, // User Sid
BOOL bSetOrRestore // set or restore the security setting
) { DWORD dwRet; HRESULT hr; TCHAR szKeyName[MAX_PATH*2]; TCHAR szKeyBuf[MAX_PATH*2];
if (lpszUsersid && *lpszUsersid) { if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("\\%s"), lpSubKeyName))) goto Exit1; } else if (hRootKey == HKEY_LOCAL_MACHINE) { if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("HKLM\\%s"), lpSubKeyName))) goto Exit1; } else if (hRootKey == HKEY_CLASSES_ROOT) { if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("HKCR\\%s"), lpSubKeyName))) goto Exit1; } RenameRegRoot(szKeyName, szKeyBuf, 2*MAX_PATH-1, lpszUsersid, NULL); dwRet = AdjustObjectSecurity(szKeyBuf, SE_REGISTRY_KEY, bSetOrRestore); goto Exit;
Exit1: dwRet = HRESULT_CODE(hr); Exit: return dwRet; }
//-----------------------------------------------------------------------------
//
// Function: GetFirstNTFSDrive
//
// Descrip: Get the first NTFS drive in the system.
//
// Returns: S_OK - Found NTFS partition
// S_FALSE - NTFS partition not found, return system drive instead
// Else - Error occured
//
// Notes: none
//
// History: 04/25/2002 Rerkboos Created
//
// Notes: none
//
//-----------------------------------------------------------------------------
HRESULT GetFirstNTFSDrive( LPTSTR lpBuffer, // Buffer to store first NTFS drive
DWORD cchBuffer // Size of buffer in TCHAR
) { HRESULT hr = S_OK; DWORD dwRet; TCHAR szDrives[MAX_PATH]; LPCTSTR lpDrive; BOOL bIsNTFS = FALSE;
dwRet = GetLogicalDriveStrings(ARRAYSIZE(szDrives), szDrives); if (dwRet > 0) { lpDrive = MultiSzTok(szDrives);
while (lpDrive != NULL) { hr = IsNTFS((LPTSTR) lpDrive, &bIsNTFS); if (SUCCEEDED(hr)) { if (bIsNTFS) { lstrcpyn(lpBuffer, lpDrive, 3); return S_OK; } }
lpDrive = MultiSzTok(NULL); } }
// If we reach here, no NTFS partition is found
// return System drive to caller instead
hr = S_FALSE; if (!GetEnvironmentVariable(TEXT("HOMEDRIVE"), lpBuffer, cchBuffer)) { hr = HRESULT_FROM_WIN32(GetLastError()); }
return hr; }
//-----------------------------------------------------------------------------
//
// Function: DuplicateString
//
// Synopsis: Duplicate the orinal string to a newly allocated buffer.
//
// Returns: S_OK if succeeded
//
// History: 06/03/2002 rerkboos created
//
// Notes: Caller need to free the allocated buffer using MEMFREE() macro
// or HeapFree() API.
//
//-----------------------------------------------------------------------------
HRESULT DuplicateString( LPTSTR *plpDstString, // Pointer to the newly allocated buffer
LPDWORD lpcchDstString, // Pointer to store size of buffer (in TCHAR)
LPCTSTR lpOrgString // Original string to duplicate
) { HRESULT hr;
if (plpDstString == NULL || lpcchDstString == NULL) { return E_INVALIDARG; }
*lpcchDstString = lstrlen(lpOrgString) + 1; *plpDstString = MEMALLOC(*lpcchDstString * sizeof(TCHAR)); if (*plpDstString != NULL) { hr = StringCchCopy(*plpDstString, *lpcchDstString, lpOrgString); if (FAILED(hr)) { // Free the memory if failed to copy the string
MEMFREE(*plpDstString); } } else { *lpcchDstString = 0; hr = E_OUTOFMEMORY; }
return hr; }
HRESULT SetProtectedRenamesFlag( BOOL bSet ) { HKEY hKey; long rslt = ERROR_SUCCESS; HRESULT hr = S_OK;
rslt = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\Session Manager"), 0, KEY_SET_VALUE, &hKey);
if (rslt == ERROR_SUCCESS) { DWORD Value = bSet ? 1 : 0; rslt = RegSetValueEx(hKey, TEXT("AllowProtectedRenames"), 0, REG_DWORD, (LPBYTE)&Value, sizeof(DWORD)); RegCloseKey(hKey);
if (rslt != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(rslt); } } else { hr = HRESULT_FROM_WIN32(rslt); } return hr; }
LONG SDBCleanup( OUT LPTSTR lpSecDatabase, IN DWORD cchLen, OUT LPBOOL lpCleanupFailed ) { char aszSdbFile[MAX_PATH+1+MAX_PATH]; TCHAR wszSdbFile[MAX_PATH+1+MAX_PATH]; TCHAR wszWindir[MAX_PATH+1]; TCHAR szSdbLogFiles[MAX_PATH+1+MAX_PATH]; TCHAR szSdbLogFileRoot[MAX_PATH+1+MAX_PATH],szBackupLogFileRoot[MAX_PATH+1+MAX_PATH]; JET_DBINFOMISC jetdbinfo; JET_ERR jetError; long lerr = ERROR_SUCCESS; HRESULT hr; if (!GetSystemWindowsDirectory(wszSdbFile, ARRAYSIZE(wszSdbFile)-MAX_PATH)) { DPF(APPerr, TEXT("Failed to get WINDIR")); lerr = GetLastError(); goto EXIT; } if (!GetSystemWindowsDirectory(wszWindir, ARRAYSIZE(wszWindir))) { DPF(APPerr, TEXT("Failed to get WINDIR")); lerr = GetLastError(); goto EXIT; }
hr = StringCchCopy(szSdbLogFiles,ARRAYSIZE(szSdbLogFiles),wszWindir); hr = StringCchCopy(szSdbLogFileRoot,ARRAYSIZE(szSdbLogFileRoot),wszWindir); hr = StringCchCopy(szBackupLogFileRoot,ARRAYSIZE(szBackupLogFileRoot),wszWindir);
ConcatenatePaths(szSdbLogFileRoot,TEXT("\\Security"),ARRAYSIZE(szSdbLogFileRoot)); ConcatenatePaths(szBackupLogFileRoot,TEXT("\\$CLMT_BACKUP$"),ARRAYSIZE(szBackupLogFileRoot)); ConcatenatePaths(szSdbLogFiles,TEXT("\\Security\\edb?????.log"),ARRAYSIZE(szSdbLogFiles)); hr = StringCbCat(wszSdbFile, ARRAYSIZE(wszSdbFile), TEXT("\\Security\\Database\\secedit.sdb")); if (lpSecDatabase) { hr = StringCchCopy(lpSecDatabase,cchLen,wszSdbFile); } WideCharToMultiByte( CP_ACP, 0, wszSdbFile, -1,aszSdbFile,ARRAYSIZE(aszSdbFile),NULL,NULL);
jetError = JetGetDatabaseFileInfo(aszSdbFile,&jetdbinfo,sizeof(JET_DBINFOMISC),JET_DbInfoMisc); if (jetError != JET_errSuccess) { if (JET_errFileNotFound == jetError) { lerr = ERROR_SUCCESS; } else { lerr = jetError; } goto EXIT; }
EXIT: if (lerr == ERROR_SUCCESS) { if (jetdbinfo.dbstate == 2) { if (lpCleanupFailed) { *lpCleanupFailed = TRUE; } } else { WIN32_FIND_DATA FindFileData; HANDLE hFile = FindFirstFile(szSdbLogFiles,&FindFileData); if (hFile != INVALID_HANDLE_VALUE) { do { TCHAR szOld[MAX_PATH+1+MAX_PATH],szNew[MAX_PATH+1+MAX_PATH];
hr = StringCchCopy(szOld,ARRAYSIZE(szOld),szSdbLogFileRoot); hr = StringCchCopy(szNew,ARRAYSIZE(szNew),szBackupLogFileRoot);
ConcatenatePaths(szOld,FindFileData.cFileName ,ARRAYSIZE(szOld)); ConcatenatePaths(szNew,FindFileData.cFileName ,ARRAYSIZE(szNew)); AddFolderRename(szOld,szNew,TYPE_FILE_MOVE,NULL); }while (FindNextFile(hFile,&FindFileData)); FindClose(hFile); } if (lpCleanupFailed) { *lpCleanupFailed = FALSE; } } } return lerr; }
//-----------------------------------------------------------------------
//
// Function: DeleteDirectory
//
// Descrip: Delete the directory and files inside.
//
// Returns: S_OK if function succeeded.
// S_FALSE if source directory does not exist
// else if error occured
//
// Notes: none
//
// History: 07/13/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------
HRESULT DeleteDirectory( LPCTSTR lpDir ) { HRESULT hr = S_OK; BOOL bRet; WIN32_FIND_DATA FindFileData; HANDLE hFile; TCHAR szFile[2 * MAX_PATH]; TCHAR szSearchPath[2 * MAX_PATH];
if (!IsDirExisting((LPTSTR) lpDir)) { return S_FALSE; }
// Compose the file path inside specified directory
hr = StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), lpDir); if (SUCCEEDED(hr)) { bRet = ConcatenatePaths(szSearchPath, TEXT("*"), ARRAYSIZE(szSearchPath)); if (!bRet) { hr = E_UNEXPECTED; return hr; } } else { return hr; }
//
// Delete all files and subdirectores under specified directory
//
hFile = FindFirstFileEx(szSearchPath, FindExInfoStandard, &FindFileData, FindExSearchLimitToDirectories, NULL, 0); if (hFile != INVALID_HANDLE_VALUE) { while (SUCCEEDED(hr)) { // Ignore "." and ".." folders
if (MyStrCmpI(FindFileData.cFileName, TEXT(".")) != LSTR_EQUAL && MyStrCmpI(FindFileData.cFileName, TEXT("..")) != LSTR_EQUAL) { hr = StringCchCopy(szFile, ARRAYSIZE(szFile), lpDir); if (FAILED(hr)) { break; }
bRet = ConcatenatePaths(szFile, FindFileData.cFileName, ARRAYSIZE(szFile)); if (!bRet) { hr = E_UNEXPECTED; break; }
//
// Check if the file is a directory or not
//
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // The file is a directory, do a recursive call
// to delete contents inside it
hr = DeleteDirectory(szFile); if (FAILED(hr)) { break; } } else { // This is just a file, delete it
bRet = DeleteFile(szFile); if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); break; } } }
// Get the next file in source directory
bRet = FindNextFile(hFile, &FindFileData); if (!bRet) { hr = HRESULT_FROM_WIN32(GetLastError()); } }
FindClose(hFile);
if (HRESULT_CODE(hr) == ERROR_NO_MORE_FILES) { // Delete itself
bRet = RemoveDirectory(lpDir); if (bRet) { // function succeeded
hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } } else { hr = HRESULT_FROM_WIN32(GetLastError()); }
return hr; }
//-----------------------------------------------------------------------
//
// Function: MyDeleteFile
//
// Descrip: Delete the specified file. The function will set the file
// attribute to Normal before deletion
//
// Returns: S_OK if function succeeded.
// S_FALSE if source directory does not exist
// else if error occured
//
// Notes: none
//
// History: 07/13/2002 rerkboos created
//
// Notes: none
//
//-----------------------------------------------------------------------
HRESULT MyDeleteFile( LPCTSTR lpFile ) { HRESULT hr; BOOL bRet;
bRet = SetFileAttributes(lpFile, FILE_ATTRIBUTE_NORMAL); if (bRet) { bRet = DeleteFile(lpFile); }
hr = (bRet ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
return hr; }
HRESULT GetDCInfo( PBOOL pbIsDC,//whether is a DC
LPTSTR lpszDCName,//if is DC, the DC name
PDWORD pcchLen)//buffer size for lpszDCName
{ PBYTE pdsInfo = NULL; DWORD dwErr = ERROR_SUCCESS; HRESULT hr = S_OK; if (!pbIsDC) { hr = E_INVALIDARG; goto Exit; }
//
// Check if the machine is Domain Controller or not
//
dwErr = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, &pdsInfo); if (dwErr == ERROR_SUCCESS) { DSROLE_MACHINE_ROLE dsMachineRole;
dsMachineRole = ((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->MachineRole;
if (dsMachineRole == DsRole_RoleBackupDomainController || dsMachineRole == DsRole_RolePrimaryDomainController) { *pbIsDC = TRUE; if (pcchLen) { if (lpszDCName) { hr = StringCchCopy(lpszDCName,*pcchLen, ((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->DomainNameFlat); } //
*pcchLen = lstrlen(((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->DomainNameFlat)+ 1; } } else { *pbIsDC = FALSE; } } else { hr = HRESULT_FROM_WIN32(dwErr); pdsInfo = NULL; goto Exit; }
Exit: if (pdsInfo) { DsRoleFreeMemory(pdsInfo); } return hr;
} HRESULT GetFQDNForExchange2k(LPTSTR *lplpFQDN) { LPTSTR lpExchangeFormat = TEXT("LDAP://CN=1,CN=SMTP,CN=Protocols,CN=%s,CN=Servers,CN=%s,CN=Administrative Groups,CN=%s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%s"); BOOL bIsDC; TCHAR szDcName[MAX_PATH+1],szCompname[MAX_PATH+1]; DWORD cchSize; TCHAR szCurrUsrname[MAX_PATH+1]; LPTSTR lpFQDNCurrUsr = NULL,lpFQDNSuffix,lpFQDNWithldap = NULL; DWORD cchPathWithLDAP; TCHAR szExchgeReg[2*MAX_PATH]; LPTSTR lpszAdminGroupName = NULL,lpszOrgName = NULL,lpStart,lpEnd; TCHAR cTmp; HRESULT hr; LONG lstatus;
cchSize = ARRAYSIZE(szCurrUsrname); if (!GetUserName(szCurrUsrname, &cchSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } cchSize = ARRAYSIZE(szDcName); hr = GetDCInfo(&bIsDC,szDcName,&cchSize); if (FAILED(hr) || !bIsDC) { if (!bIsDC) { hr =S_FALSE; } goto Exit; } cchSize = ARRAYSIZE(szCompname); if (!GetComputerName(szCompname,&cchSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (S_OK !=GetFQDN(szCurrUsrname,szDcName,&lpFQDNCurrUsr)) { lpFQDNCurrUsr = NULL; goto Exit; } lpFQDNSuffix = StrStrI(lpFQDNCurrUsr, TEXT("=Users,")); if (!lpFQDNSuffix) { hr = S_FALSE; goto Exit; } lpFQDNSuffix += lstrlen(TEXT("=Users,"));
cchSize = ARRAYSIZE(szExchgeReg); lstatus= RegGetValue(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"), TEXT("SiteDN"), NULL, (LPBYTE)szExchgeReg, &cchSize); if (ERROR_SUCCESS != lstatus)
{ hr = HRESULT_FROM_WIN32(lstatus); goto Exit; } lpszAdminGroupName = malloc(ARRAYSIZE(szExchgeReg) * sizeof(TCHAR)); lpszOrgName = malloc(ARRAYSIZE(szExchgeReg) * sizeof(TCHAR)); if (!lpszAdminGroupName || !lpszOrgName) { hr = E_OUTOFMEMORY; goto Exit; } //try to get exchnage admin group group name
//by default it is First Administrative Group
lpStart = StrStrI(szExchgeReg, TEXT("/ou=")); if (lpStart) { lpStart = lpStart + lstrlen(TEXT("/ou=")); if (!*lpStart) { hr = S_FALSE; goto Exit; } } else { hr = S_FALSE; goto Exit; } lpEnd = StrStrI(lpStart, TEXT("/")); if (lpEnd) { cTmp = *lpEnd; *lpEnd = TEXT('\0'); } hr = StringCchCopy(lpszAdminGroupName,ARRAYSIZE(szExchgeReg),lpStart); if (lpEnd) { *lpEnd = cTmp; }
//try to get ornization name
lpStart = StrStrI(szExchgeReg, TEXT("/o=")); if (lpStart) { lpStart = lpStart + lstrlen(TEXT("/o=")); if (!*lpStart) { hr = S_FALSE; goto Exit; } } else { hr = S_FALSE; goto Exit; } lpEnd = StrStrI(lpStart, TEXT("/")); if (lpEnd) { cTmp = *lpEnd; *lpEnd = TEXT('\0'); } hr = StringCchCopy(lpszOrgName,ARRAYSIZE(szExchgeReg),lpStart); if (lpEnd) { *lpEnd = cTmp; } cchPathWithLDAP = lstrlen(lpFQDNSuffix) + lstrlen(szDcName) + lstrlen(szCompname) + lstrlen(lpExchangeFormat) + lstrlen(lpszOrgName) + lstrlen(lpszAdminGroupName)+ MAX_PATH; if (! (lpFQDNWithldap = (LPTSTR) malloc(cchPathWithLDAP * sizeof(TCHAR)))) { hr = E_OUTOFMEMORY; goto Exit; } hr = StringCchPrintf(lpFQDNWithldap, cchPathWithLDAP, lpExchangeFormat, szCompname, lpszAdminGroupName, lpszOrgName, lpFQDNSuffix); Exit: if (hr == S_OK) { *lplpFQDN = lpFQDNWithldap; } else { FreePointer(lpFQDNWithldap); *lplpFQDN = NULL; } FreePointer(lpFQDNCurrUsr); FreePointer(lpszAdminGroupName); FreePointer(lpszOrgName); return hr; }
HRESULT GetFQDNForFrs(LPTSTR *lplpFQDN) { BOOL bIsDC; TCHAR szDcName[MAX_PATH+1],szCompname[MAX_PATH+1]; DWORD cchSize; TCHAR szCurrUsrname[MAX_PATH+1]; LPTSTR lpFQDNCurrUsr = NULL,lpFQDNSuffix,lpFQDNWithldap = NULL; LPTSTR lpFrsFormat = TEXT("LDAP://CN=Domain System Volume (SYSVOL share),CN=NTFRS Subscriptions,CN=%s,OU=Domain Controllers,%s"); DWORD cchPathWithLDAP; HRESULT hr;
cchSize = ARRAYSIZE(szCurrUsrname); if (!GetUserName(szCurrUsrname, &cchSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } cchSize = ARRAYSIZE(szDcName); hr = GetDCInfo(&bIsDC,szDcName,&cchSize); if (FAILED(hr) || !bIsDC) { if (!bIsDC) { hr =S_FALSE; } goto Exit; } cchSize = ARRAYSIZE(szCompname); if (!GetComputerName(szCompname,&cchSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } if (S_OK !=GetFQDN(szCurrUsrname,szDcName,&lpFQDNCurrUsr)) { lpFQDNCurrUsr = NULL; goto Exit; } lpFQDNSuffix = StrStrI(lpFQDNCurrUsr, TEXT("=Users,")); if (!lpFQDNSuffix) { hr =S_FALSE; goto Exit; } lpFQDNSuffix += lstrlen(TEXT("=Users,")); cchPathWithLDAP = lstrlen(lpFQDNSuffix) + lstrlen(szDcName) + lstrlen(lpFrsFormat) + MAX_PATH; if (! (lpFQDNWithldap = (LPTSTR) malloc(cchPathWithLDAP * sizeof(TCHAR)))) { hr = E_OUTOFMEMORY; goto Exit; } hr = StringCchPrintf(lpFQDNWithldap, cchPathWithLDAP, lpFrsFormat, szCompname, lpFQDNSuffix); Exit: if (hr == S_OK) { *lplpFQDN = lpFQDNWithldap; } else { FreePointer(lpFQDNWithldap); *lplpFQDN = NULL; } FreePointer(lpFQDNCurrUsr); return hr;}
HRESULT AddDSObjPropUpdate2Inf( LPTSTR lpLdpPath, LPTSTR lpPropName, LPTSTR lpValue) { LPTSTR lpszOneline = NULL; DWORD cchSize ; HRESULT hr = S_OK; TCHAR szIndex[MAX_PATH]; if (!lpLdpPath || !lpPropName || !lpValue) { hr = E_INVALIDARG; goto cleanup; } cchSize = lstrlen(lpLdpPath) + lstrlen(lpPropName) + lstrlen(lpValue) + MAX_PATH; if ( ! (lpszOneline = malloc(cchSize * sizeof(TCHAR)) )) { hr = E_OUTOFMEMORY; goto cleanup; }
g_dwKeyIndex++; _itot(g_dwKeyIndex,szIndex,16); hr = StringCchPrintf(lpszOneline, cchSize, TEXT("\"%s\",\"%s\",\"%s\""),lpLdpPath,lpPropName,lpValue); if (!WritePrivateProfileString(DS_OBJ_PROPERTY_UPDATE,szIndex,lpszOneline,g_szToDoINFFileName)) { hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } hr = S_OK; cleanup: FreePointer(lpszOneline); return hr; }
HRESULT Ex2000Update() { LPTSTR lpObjPath = NULL; LPTSTR lpBadMailDirectory = NULL, lpPickupDirectory = NULL, lpQueueDirectory = NULL; LPTSTR lpNewBadMailDirectory = NULL, lpNewPickupDirectory = NULL, lpNewQueueDirectory = NULL; HRESULT hr;
hr = GetFQDNForExchange2k(&lpObjPath); if (hr != S_OK) { goto exit; } hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpBadMailDirectory"),&lpBadMailDirectory,NULL); if (hr == S_OK) { if (lpNewBadMailDirectory = ReplaceLocStringInPath(lpBadMailDirectory,TRUE)) { AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpBadMailDirectory"),lpNewBadMailDirectory); } } hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpPickupDirectory"),&lpPickupDirectory,NULL); if (hr == S_OK) { if (lpNewPickupDirectory = ReplaceLocStringInPath(lpPickupDirectory,TRUE)) { AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpPickupDirectory"),lpNewPickupDirectory); } } hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpQueueDirectory"),&lpQueueDirectory,NULL); if (hr == S_OK) { if (lpNewQueueDirectory = ReplaceLocStringInPath(lpQueueDirectory,TRUE)) { AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpQueueDirectory"),lpNewQueueDirectory); } } exit: FreePointer(lpObjPath); FreePointer(lpBadMailDirectory); FreePointer(lpPickupDirectory); FreePointer(lpQueueDirectory); if (lpNewBadMailDirectory) { MEMFREE(lpNewBadMailDirectory); } if (lpNewPickupDirectory) { MEMFREE(lpNewPickupDirectory); } if (lpNewQueueDirectory) { MEMFREE(lpNewQueueDirectory); } return hr; }
HRESULT FRSUpdate() { LPTSTR lpObjPath = NULL; LPTSTR lpfRSRootPath = NULL, lpfRSStagingPath = NULL; LPTSTR lpNewfRSRootPath = NULL, lpNewfRSStagingPath = NULL; BOOL bChanged = FALSE; HRESULT hr; TCHAR szSysVolPath[2*MAX_PATH],szSysVolPath2[2*MAX_PATH]; DWORD cchSize = ARRAYSIZE(szSysVolPath); WIN32_FIND_DATA FindFileData; HANDLE hFile ;
hr = GetFQDNForFrs(&lpObjPath); if (hr != S_OK) { goto exit; } hr = PropertyValueHelper(lpObjPath,TEXT("fRSRootPath"),&lpfRSRootPath,NULL); if (hr == S_OK) { if (lpNewfRSRootPath = ReplaceLocStringInPath(lpfRSRootPath,TRUE)) { AddDSObjPropUpdate2Inf(lpObjPath,TEXT("fRSRootPath"),lpNewfRSRootPath); bChanged = TRUE; } }
hr = PropertyValueHelper(lpObjPath,TEXT("fRSStagingPath"),&lpfRSStagingPath,NULL); if (hr == S_OK) { if (lpNewfRSStagingPath = ReplaceLocStringInPath(lpfRSStagingPath,TRUE)) { AddDSObjPropUpdate2Inf(lpObjPath,TEXT("fRSStagingPath"),lpNewfRSStagingPath); bChanged = TRUE; } } if (bChanged) { TCHAR szVal[MAX_PATH];
_itot(210,szVal,10); hr = AddRegValueRename(TEXT("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Backup/Restore\\Process at Startup"), TEXT("BurFlags"), NULL, NULL, szVal, REG_DWORD, 0, NULL); }
if (S_OK != GetSharePath(TEXT("SYSVOL"),szSysVolPath,&cchSize)) { goto exit; } hr = StringCchCopy(szSysVolPath2,ARRAYSIZE(szSysVolPath2),szSysVolPath); ConcatenatePaths(szSysVolPath2,TEXT("*.*"),ARRAYSIZE(szSysVolPath2)); hFile = FindFirstFile(szSysVolPath2,&FindFileData); if (hFile != INVALID_HANDLE_VALUE) { do { TCHAR szEnrty[MAX_PATH+1+MAX_PATH]; LPTSTR lpNewLinkPath = NULL, lpNewLinkData = NULL; TCHAR szLinkValue[MAX_PATH+1+MAX_PATH];
if(0 == MyStrCmpI(FindFileData.cFileName , TEXT("."))) { continue; } if(0 == MyStrCmpI(FindFileData.cFileName , TEXT(".."))) { continue; } hr = StringCchCopy(szEnrty,ARRAYSIZE(szEnrty),szSysVolPath); ConcatenatePaths(szEnrty,FindFileData.cFileName ,ARRAYSIZE(szEnrty)); if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { continue; } if (!GetSymbolicLink(szEnrty,szLinkValue,ARRAYSIZE(szLinkValue))) { continue; } if (!(lpNewLinkPath = ReplaceLocStringInPath(szLinkValue,TRUE))) { continue; } if (!(lpNewLinkData = ReplaceLocStringInPath(szEnrty,TRUE))) { lpNewLinkData = szEnrty; } AddHardLinkEntry(lpNewLinkData,lpNewLinkPath,TEXT("1"),NULL,TEXT("0"),NULL); if (lpNewLinkPath && lpNewLinkData != szEnrty) { MEMFREE(lpNewLinkPath); } if (lpNewLinkData) { MEMFREE(lpNewLinkData); } }while (FindNextFile(hFile,&FindFileData)); FindClose(hFile); }
exit: FreePointer(lpObjPath); FreePointer(lpfRSRootPath); FreePointer(lpfRSStagingPath); if (lpNewfRSRootPath) { MEMFREE(lpNewfRSRootPath); } if (lpNewfRSStagingPath) { MEMFREE(lpNewfRSStagingPath); } return hr;
}
HRESULT GetSharePath( LPTSTR lpShareName, LPTSTR lpSharePath, PDWORD pcchSize) { HKEY hkey = NULL; LONG lstatus; HRESULT hr; UINT i = 0; LPTSTR lpValueName = NULL, lpValueData = NULL; DWORD cchValueName, cchValueData, numofentry; BOOL bNameMatchFound = FALSE; LPTSTR lpPath;
if (!lpShareName || !pcchSize) { hr = E_INVALIDARG; } lstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"), 0, KEY_READ, &hkey); if (ERROR_SUCCESS != lstatus) { hr = HRESULT_FROM_WIN32(lstatus); goto exit; } lstatus = RegQueryInfoKey(hkey, NULL, NULL, 0, NULL, NULL, NULL, &numofentry, &cchValueName, &cchValueData, NULL, NULL); if ( lstatus != ERROR_SUCCESS ) { hr = HRESULT_FROM_WIN32(lstatus); goto exit; } if (!numofentry) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); goto exit; } cchValueName++; cchValueData++; lpValueName = malloc(cchValueName * sizeof(TCHAR)); lpValueData = malloc(cchValueData * sizeof(TCHAR)); if (!lpValueName || !lpValueData) { hr = E_OUTOFMEMORY; goto exit; } for (i =0; i< numofentry; i++) { DWORD cchCurrValueName, cchCurrValueData; DWORD dwType;
cchCurrValueName = cchValueName; cchCurrValueData = cchValueData; lstatus = RegEnumValue(hkey, i, lpValueName, &cchCurrValueName, NULL, &dwType, (LPBYTE)lpValueData,&cchCurrValueData); if ( (lstatus != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ) || MyStrCmpI(lpShareName,lpValueName) ) { continue; } lpPath = lpValueData; while (*lpPath) { if (StrStrI(lpPath, TEXT("Path="))) { lpPath += lstrlen(TEXT("Path=")); bNameMatchFound = TRUE; break; } lpPath = lpPath + lstrlen(lpPath) + 1; } if (bNameMatchFound) { break; } } if (bNameMatchFound) { if (*pcchSize < (UINT)lstrlen(lpPath) +1) { *pcchSize = lstrlen(lpPath) +1; hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA); goto exit; } *pcchSize = lstrlen(lpPath) +1; if (lpSharePath) { hr = StringCchCopy(lpSharePath,*pcchSize,lpPath); } else { hr = S_OK; } } else { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); goto exit; } exit: FreePointer(lpValueName); FreePointer(lpValueData); if (hkey) { RegCloseKey(hkey); } return hr; }
HRESULT Sz2MultiSZ( IN OUT LPTSTR lpsz, IN TCHAR chSeperator) { HRESULT hr; LPTSTR lp, lpSep; if (!lpsz) { hr = E_INVALIDARG; goto Cleanup; } lp = lpsz; while (*lp && (lpSep = StrChr(lp,chSeperator))) { *lpSep = TEXT('\0'); lp = lpSep + 1; } if (*lp) { lp = lp + lstrlen(lp) + 1; *lp = TEXT('\0'); } hr = S_OK; Cleanup: return hr; }
HRESULT ConstructUIReplaceStringTable( LPTSTR lpszOld, LPTSTR lpszNew, PREG_STRING_REPLACE pTable) {
DWORD dwNumOld, dwNumNew;
if (!lpszOld || !lpszNew) { return E_INVALIDARG; } dwNumOld = MultiSZNumOfString(lpszOld); dwNumNew = MultiSZNumOfString(lpszNew);
if (!dwNumOld || !dwNumNew || (dwNumOld != dwNumNew)) { return E_INVALIDARG; } pTable->nNumOfElem = dwNumNew; pTable->cchUserName = 0; pTable->szUserNameLst = NULL; pTable->cchSearchString = MultiSzLen(lpszOld); pTable->lpSearchString = lpszOld; pTable->cchReplaceString = MultiSzLen(lpszNew); pTable->lpReplaceString = lpszNew; pTable->cchAttribList = 0; pTable->lpAttrib = NULL; pTable->cchFullStringList = 0; pTable->lpFullStringList = NULL; pTable->cchMaxStrLen = 0;
return S_OK; }
HRESULT MakeDOInfCopy() { TCHAR szBackupDir[MAX_PATH]; HRESULT hr; TCHAR szDoInf[2*MAX_PATH],szDoInfBackup[2*MAX_PATH];
if (!GetSystemWindowsDirectory(szBackupDir, ARRAYSIZE(szBackupDir))) { //BUGBUG:Xiaoz:Add DLG pop up for failure
DPF(APPerr, TEXT("MakeDOInfCopy:Failed to get WINDIR")); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } ConcatenatePaths(szBackupDir,CLMT_BACKUP_DIR,ARRAYSIZE(szBackupDir)); hr = StringCchCopy(szDoInf,ARRAYSIZE(szDoInf),szBackupDir); hr = StringCchCopy(szDoInfBackup,ARRAYSIZE(szDoInfBackup),szBackupDir);
ConcatenatePaths(szDoInf,TEXT("clmtdo.inf"),ARRAYSIZE(szDoInf)); ConcatenatePaths(szDoInfBackup,TEXT("clmtdo.bak"),ARRAYSIZE(szDoInfBackup));
if (!CopyFile(szDoInf,szDoInfBackup,FALSE)) { DPF(APPerr, TEXT("MakeDOInfCopy:CopyFile failed")); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } hr = S_OK; Exit: return hr; }
VOID RemoveSubString( LPTSTR lpSrcString, LPCTSTR lpSubString ) { LPTSTR lpMatchedStr; DWORD dwSubStrLen;
lpMatchedStr = StrStr(lpSrcString, lpSubString); if (lpMatchedStr != NULL) { dwSubStrLen = lstrlen(lpSubString);
while (*(lpMatchedStr + dwSubStrLen) != TEXT('\0')) { *(lpMatchedStr) = *(lpMatchedStr + dwSubStrLen); lpMatchedStr++; }
*lpMatchedStr = TEXT('\0'); } }
|