You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1797 lines
59 KiB
1797 lines
59 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
inf.c
|
|
|
|
Abstract:
|
|
|
|
Miscellaneous routines for the INF File Operation
|
|
|
|
Author:
|
|
|
|
Xiaofeng Zang (xiaoz) 17-Sep-2001 Created
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "clmt.h"
|
|
|
|
HRESULT RegistryRename(HINF hInf, LPTSTR lpszSection,HKEY hKeyRoot,LPTSTR lpszUser);
|
|
HRESULT FolderMove(HINF hInf, LPTSTR lpszSection,BOOL bAnalyze);
|
|
HRESULT ChangeServiceStartupType(LPCTSTR, DWORD, DWORD);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
RegistryRename(HINF hInf, LPTSTR lpszSection,HKEY hKeyRoot,LPTSTR lpszUser)
|
|
{
|
|
UINT LineCount,LineNo;
|
|
INFCONTEXT InfContext;
|
|
DWORD dwStrType;
|
|
LPTSTR pSubKeyPath;
|
|
HKEY hKey;
|
|
TCHAR szRenameType[MAX_PATH],szStringType[MAX_PATH];
|
|
DWORD dwRenameType,dwStringType;
|
|
DWORD cchMaxOldKeyPathLength = 0;
|
|
DWORD cchMaxNewKeyPathLength = 0;
|
|
DWORD cchMaxOldNameLength = 0;
|
|
DWORD cchMaxNewNameLength = 0;
|
|
DWORD cchMaxOldDataLength = 0;
|
|
DWORD cchMaxNewDataLength = 0;
|
|
DWORD dwAttrib = 0;
|
|
LPTSTR lpszOldKey,lpszNewKey,lpszOldName,lpszNewName,lpszOldValue,lpszNewValue;
|
|
HRESULT hr;
|
|
LONG lstatus;
|
|
|
|
|
|
lpszOldKey = lpszNewKey = lpszOldName = lpszNewName
|
|
= lpszOldValue = lpszNewValue = NULL;
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
DPF(INFwar ,TEXT("section name %s is empty failed !"),lpszSection);
|
|
goto Cleanup;
|
|
}
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
DWORD cchTmpOldKeyPathLength,cchTmpNewKeyPathLength ,cchTmpOldNameLength ,
|
|
cchTmpNewNameLength,cchTmpOldDataLength,cchTmpNewDataLength;
|
|
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szRenameType,MAX_PATH,NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("get [%s] 's line %n 's Field 0 failed !"),lpszSection, LineNo);
|
|
continue;
|
|
}
|
|
|
|
cchTmpOldKeyPathLength = cchTmpNewKeyPathLength = cchTmpOldNameLength
|
|
= cchTmpNewNameLength = cchTmpOldDataLength = cchTmpNewDataLength = 0;
|
|
dwRenameType = _tstoi(szRenameType);
|
|
switch (dwRenameType)
|
|
{
|
|
case TYPE_VALUE_RENAME:
|
|
if (!SetupGetStringField(&InfContext,2,szStringType,MAX_PATH,NULL)
|
|
|| !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpOldKeyPathLength)
|
|
|| !SetupGetStringField(&InfContext,4,NULL,0,&cchTmpOldNameLength)
|
|
|| ! SetupGetStringField(&InfContext,5,NULL,0,&cchTmpOldDataLength)
|
|
|| ! SetupGetStringField(&InfContext,6,NULL,0,&cchTmpNewDataLength))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3,4,5,6 failed !"),lpszSection ,InfContext.Line);
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
case TYPE_VALUENAME_RENAME:
|
|
if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldKeyPathLength)
|
|
|| !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpOldNameLength)
|
|
|| ! SetupGetStringField(&InfContext,4,NULL,0,&cchTmpNewNameLength))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4,5 failed !"),lpszSection ,InfContext.Line);
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
case TYPE_KEY_RENAME:
|
|
if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldKeyPathLength)
|
|
|| !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpNewKeyPathLength))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4 failed !"),lpszSection ,InfContext.Line);
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
}
|
|
cchMaxOldKeyPathLength = max(cchTmpOldKeyPathLength,cchMaxOldKeyPathLength);
|
|
cchMaxNewKeyPathLength = max(cchTmpNewKeyPathLength,cchMaxNewKeyPathLength);
|
|
cchMaxOldNameLength = max(cchTmpOldNameLength,cchMaxOldNameLength);
|
|
cchMaxNewNameLength = max(cchTmpNewNameLength,cchMaxNewNameLength);
|
|
cchMaxOldDataLength = max(cchTmpOldDataLength,cchMaxOldDataLength);
|
|
cchMaxNewDataLength = max(cchTmpNewDataLength,cchMaxNewDataLength);
|
|
}
|
|
if (cchMaxOldKeyPathLength)
|
|
{
|
|
if (!(lpszOldKey = malloc(++cchMaxOldKeyPathLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxNewKeyPathLength)
|
|
{
|
|
if (!(lpszNewKey = malloc(++cchMaxNewKeyPathLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxOldNameLength)
|
|
{
|
|
if (!(lpszOldName = malloc(++cchMaxOldNameLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxNewNameLength)
|
|
{
|
|
if (!(lpszNewName = malloc(++cchMaxNewNameLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxOldDataLength)
|
|
{
|
|
if (!(lpszOldValue = malloc(++cchMaxOldDataLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxNewDataLength)
|
|
{
|
|
if (!(lpszNewValue = malloc(++cchMaxNewDataLength * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szRenameType,MAX_PATH,NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("get [%s] 's line %n 's Field 0 failed !"),lpszSection, LineNo);
|
|
continue;
|
|
}
|
|
dwRenameType = _tstoi(szRenameType);
|
|
switch (dwRenameType)
|
|
{
|
|
case TYPE_VALUE_RENAME:
|
|
if (!SetupGetStringField(&InfContext,2,szStringType,MAX_PATH,NULL)
|
|
|| !SetupGetStringField(&InfContext,3,lpszOldKey,cchMaxOldKeyPathLength,NULL)
|
|
|| ! SetupGetStringField(&InfContext,4,lpszOldName,cchMaxOldNameLength,NULL)
|
|
|| ! SetupGetStringField(&InfContext,5,lpszOldValue,cchMaxOldDataLength,NULL)
|
|
|| ! SetupGetStringField(&InfContext,6,lpszNewValue ,cchMaxNewDataLength,NULL))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4,5 failed !"),lpszSection ,InfContext.Line);
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
goto Cleanup;
|
|
}
|
|
if (!Str2KeyPath(lpszOldKey,&hKey,&pSubKeyPath))
|
|
{
|
|
DPF(INFerr ,TEXT("format errorin line %d: %s !"),LineNo,lpszOldKey);
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
goto Cleanup;
|
|
}
|
|
if (hKeyRoot)
|
|
{
|
|
hKey = hKeyRoot;
|
|
}
|
|
dwStringType = _tstoi(szStringType);
|
|
lstatus = RegResetValue(hKey, pSubKeyPath,lpszOldName,dwStringType,lpszOldValue,lpszOldValue, 0, NULL);
|
|
if (lstatus == ERROR_SUCCESS)
|
|
{
|
|
hr = AddRegValueRename(pSubKeyPath,lpszOldName,NULL,lpszOldValue,lpszNewValue,dwStringType,dwAttrib,lpszUser);
|
|
//Add error checking here
|
|
}
|
|
break;
|
|
case TYPE_VALUENAME_RENAME:
|
|
break;
|
|
case TYPE_KEY_RENAME:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
FreePointer(lpszOldKey);
|
|
FreePointer(lpszNewKey);
|
|
FreePointer(lpszOldName);
|
|
FreePointer(lpszNewName);
|
|
FreePointer(lpszOldValue);
|
|
FreePointer(lpszNewValue);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT FolderMove(HINF hInf, LPTSTR lpszSection,BOOL bAnalyze)
|
|
{
|
|
LPTSTR lpszOldFolder = NULL,lpszNewFolder = NULL,lpExcludeFileList = NULL;
|
|
DWORD cchMaxOldFolderSize = 0,cchMaxNewFolderSize = 0,cchMaxExcludeFileListSize = 0;
|
|
HRESULT hr;
|
|
UINT LineCount,LineNo;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szType[MAX_PATH];
|
|
DWORD dwType;
|
|
|
|
|
|
if( (hInf == INVALID_HANDLE_VALUE) || (!lpszSection) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
DPF(INFwar ,TEXT("section name %s is empty failed !"),lpszSection);
|
|
goto Cleanup;
|
|
}
|
|
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
DWORD cchTmpOldFolderSize = 0,cchTmpNewFolderSize = 0,cchTmpExcludeFileListSize = 0;
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szType,MAX_PATH,NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("get [%s] 's line %d 's Field 0 failed !"),lpszSection, LineNo);
|
|
continue;
|
|
}
|
|
|
|
dwType = _tstoi(szType);
|
|
switch (dwType)
|
|
{
|
|
case TYPE_SFPFILE_MOVE:
|
|
case TYPE_FILE_MOVE:
|
|
case TYPE_DIR_MOVE:
|
|
if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldFolderSize)
|
|
|| ! SetupGetStringField(&InfContext,3,NULL,0,&cchTmpNewFolderSize))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3failed !"),lpszSection ,LineNo);
|
|
goto Cleanup;
|
|
}
|
|
if (TYPE_DIR_MOVE == dwType)
|
|
{
|
|
BOOL bTmp;
|
|
bTmp = SetupGetMultiSzField(&InfContext,4,NULL,0,&cchTmpExcludeFileListSize);
|
|
if (!( bTmp && (cchTmpExcludeFileListSize >= sizeof(TCHAR))))
|
|
{
|
|
cchTmpExcludeFileListSize = 0;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
DPF(INFerr ,TEXT(" [%s] 's line %d 's Field 1 invalid value !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
break;
|
|
}
|
|
cchMaxOldFolderSize = max(cchTmpOldFolderSize,cchMaxOldFolderSize);
|
|
cchMaxNewFolderSize = max(cchTmpNewFolderSize,cchMaxNewFolderSize);
|
|
cchMaxExcludeFileListSize = max(cchTmpExcludeFileListSize,cchMaxExcludeFileListSize);
|
|
}
|
|
if (cchMaxOldFolderSize)
|
|
{ // add one more TCHAR space incase the file is SFPed in which case we need
|
|
// provide a multisz string to UnProtectSFPFiles
|
|
cchMaxOldFolderSize += 2;
|
|
if (!(lpszOldFolder = malloc(cchMaxOldFolderSize * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxNewFolderSize)
|
|
{
|
|
if (!(lpszNewFolder = malloc(++cchMaxNewFolderSize * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxExcludeFileListSize)
|
|
{
|
|
if (!(lpExcludeFileList = malloc(++cchMaxExcludeFileListSize * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
LPTSTR lpTmpExcludeList = NULL;
|
|
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szType,MAX_PATH,NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("get [%s] 's line %d 's Field 0 failed !"),lpszSection, LineNo);
|
|
continue;
|
|
}
|
|
dwType = _tstoi(szType);
|
|
if (!SetupGetStringField(&InfContext,2,lpszOldFolder,cchMaxOldFolderSize,NULL)
|
|
|| ! SetupGetStringField(&InfContext,3,lpszNewFolder,cchMaxNewFolderSize,NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3failed !"),lpszSection ,LineNo);
|
|
goto Cleanup;
|
|
}
|
|
switch (dwType)
|
|
{
|
|
case TYPE_DIR_MOVE:
|
|
if (cchMaxExcludeFileListSize)
|
|
{
|
|
DWORD dwSize;
|
|
BOOL bTmp = SetupGetMultiSzField(&InfContext,4,lpExcludeFileList,
|
|
cchMaxExcludeFileListSize,&dwSize);
|
|
if (!( bTmp && dwSize >= sizeof(TCHAR)))
|
|
{
|
|
lpTmpExcludeList = lpExcludeFileList;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpTmpExcludeList = NULL;
|
|
}
|
|
case TYPE_SFPFILE_MOVE:
|
|
case TYPE_FILE_MOVE:
|
|
if (bAnalyze)
|
|
{
|
|
AddFolderRename(lpszOldFolder,lpszNewFolder,dwType,lpTmpExcludeList);
|
|
}
|
|
else
|
|
{
|
|
if (lpTmpExcludeList)
|
|
{
|
|
LPTSTR lp = lpTmpExcludeList;
|
|
while (*lp)
|
|
{
|
|
if (!MoveFileEx(lp,NULL,MOVEFILE_DELAY_UNTIL_REBOOT))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
DPF(INFerr, TEXT("MoveFileEx(delete) failed %s,win32 error = %d"),lp,dw);
|
|
}
|
|
lp += (lstrlen(lp)+1);
|
|
}
|
|
}
|
|
if (dwType == TYPE_SFPFILE_MOVE)
|
|
{
|
|
lpszOldFolder[lstrlen(lpszOldFolder)+1] = TEXT('\0');
|
|
UnProtectSFPFiles(lpszOldFolder,NULL);
|
|
}
|
|
if (!MoveFileEx(lpszOldFolder,lpszNewFolder,MOVEFILE_DELAY_UNTIL_REBOOT))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
DPF(INFerr, TEXT("MoveFileEx(%s,%s) failed win32 error = %d"),lpszOldFolder,lpszNewFolder,dw);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
FreePointer(lpszOldFolder);
|
|
FreePointer(lpszNewFolder);
|
|
FreePointer(lpExcludeFileList);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT EnsureDoItemInfFile(
|
|
LPTSTR lpszInfFile,
|
|
size_t CchBufSize)
|
|
{
|
|
|
|
LPWSTR lpszHeader = L"[Version]\r\nsignature=\"$Windows NT$\"\r\nClassGUID={00000000-0000-0000-0000-000000000000}\r\nlayoutfile=LAYOUT.INF\r\n";
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwWritten;
|
|
DWORD dwStatusinReg;
|
|
BOOL bCureMode = FALSE;
|
|
WORD wBOM=0xFEFF;
|
|
SECURITY_ATTRIBUTES sa;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
|
|
if (!GetSystemWindowsDirectory(lpszInfFile, CchBufSize))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(INFerr, TEXT("Failed to get system directory, hr = 0x%X"), hr);
|
|
goto Exit;
|
|
}
|
|
if (!ConcatenatePaths(lpszInfFile,CLMT_BACKUP_DIR,CchBufSize))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
|
|
DPF(INFerr, TEXT("buffer size too small when creating clmtdo.inf"));
|
|
goto Exit;
|
|
}
|
|
if (!ConcatenatePaths(lpszInfFile,TEXT("CLMTDO.INF"),CchBufSize))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
|
|
DPF(INFerr, TEXT("buffer size too small when creating clmtdo.inf"));
|
|
goto Exit;
|
|
}
|
|
|
|
hr = CLMTGetMachineState(&dwStatusinReg);
|
|
//If we 've done running clmt.exe and called again, usually it's in /cure mode...
|
|
//on this case, we will append the INF file
|
|
if ( (hr != S_OK)
|
|
|| ( (CLMT_STATE_MIGRATION_DONE != dwStatusinReg)
|
|
&& (CLMT_STATE_FINISH != dwStatusinReg)
|
|
&& (CLMT_STATE_PROGRAMFILES_CURED != dwStatusinReg)) )
|
|
{
|
|
hr = CreateAdminsSd(&pSD);
|
|
if (hr != S_OK)
|
|
{
|
|
goto Exit;
|
|
}
|
|
sa.nLength = sizeof(sa);
|
|
sa.bInheritHandle = FALSE;
|
|
sa.lpSecurityDescriptor = pSD;
|
|
hFile = CreateFile(lpszInfFile,GENERIC_WRITE|GENERIC_READ,0,
|
|
&sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
|
|
hr = InitChangeLog();
|
|
}
|
|
else
|
|
{
|
|
bCureMode = TRUE;
|
|
hFile = CreateFile(lpszInfFile,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
}
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
DWORD dw = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(INFerr, TEXT("Create file %s failed with hr = 0x%X"),lpszInfFile,hr);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!bCureMode)
|
|
{
|
|
if(! WriteFile(hFile,&wBOM,sizeof(WORD),&dwWritten,NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(INFerr, TEXT("write to file %s failed with hr = 0x%X"),lpszInfFile,hr);
|
|
goto Exit;
|
|
}
|
|
if(! WriteFile(hFile,lpszHeader,lstrlenW(lpszHeader)*sizeof(TCHAR),&dwWritten,NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(INFerr, TEXT("write to file %s failed with hr = 0x%X"),lpszInfFile,hr);
|
|
goto Exit;
|
|
}
|
|
}
|
|
Exit:
|
|
if (INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
CloseHandle(hFile);
|
|
}
|
|
if (pSD)
|
|
{
|
|
LocalFree(pSD);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetMaxLenEachField(
|
|
HINF hInf,
|
|
LPTSTR lpSection,
|
|
BOOL bExitOnError,
|
|
DWORD dwMinFieldCount,
|
|
DWORD dwMaxFieldCount,
|
|
PDWORD pdwFieldValidFlag,
|
|
PDWORD pdwSizeRequired,
|
|
BOOL bMultiSZ
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
UINT LineCount,LineNo;
|
|
UINT nFieldCount, nFieldIndex;
|
|
INFCONTEXT InfContext;
|
|
UINT i;
|
|
UINT cchReqSize;
|
|
|
|
|
|
if( (hInf == INVALID_HANDLE_VALUE) || !lpSection )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
if (!dwMinFieldCount || !dwMaxFieldCount
|
|
|| ( dwMaxFieldCount < dwMinFieldCount)
|
|
|| !pdwSizeRequired)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
for (i = 0; i < dwMaxFieldCount; i++)
|
|
{
|
|
pdwSizeRequired[i] = 0;
|
|
}
|
|
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
DPF(INFwar ,TEXT("section name %s is empty failed !"),lpSection);
|
|
goto Exit;
|
|
}
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
DWORD dwNumField;
|
|
if (!SetupGetLineByIndex(hInf,lpSection,LineNo,&InfContext))
|
|
{
|
|
if (bExitOnError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
|
|
continue;
|
|
}
|
|
}
|
|
dwNumField = SetupGetFieldCount(&InfContext);
|
|
if ( (dwNumField < dwMinFieldCount) || (dwNumField > dwMaxFieldCount) )
|
|
{
|
|
if (bExitOnError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
|
|
continue;
|
|
}
|
|
}
|
|
for (nFieldIndex = 1 ; nFieldIndex <= dwNumField ; nFieldIndex++)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (pdwFieldValidFlag && !pdwFieldValidFlag[nFieldIndex])
|
|
{
|
|
continue;
|
|
}
|
|
if ((nFieldIndex == dwMaxFieldCount) && bMultiSZ)
|
|
{
|
|
bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
|
|
}
|
|
else
|
|
{
|
|
bRet = SetupGetStringField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
|
|
}
|
|
if (!bRet)
|
|
{
|
|
if (bExitOnError)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
|
|
continue;
|
|
}
|
|
}
|
|
pdwSizeRequired[nFieldIndex-1] = max(pdwSizeRequired[nFieldIndex-1],cchReqSize);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT RegUpdate(HINF hInf, HKEY hKeyUser , LPTSTR lpszUsersid)
|
|
{
|
|
#define REG_UPDATE_FIELD_COUNT 5
|
|
HRESULT hr;
|
|
LPTSTR lpszSectionName = NULL;
|
|
DWORD cChSecBuffeSize, dwRequestSize = 0;
|
|
LPTSTR lpszSectionSuffix = NULL;
|
|
UINT LineCount,LineNo,nFieldIndex;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szRegUpdateType[MAX_PATH],szStrType[MAX_PATH];
|
|
DWORD dwRegUpdateType,dwStrType;
|
|
LPTSTR lpszField[REG_UPDATE_FIELD_COUNT+1] = {NULL, szRegUpdateType, NULL, NULL, NULL, NULL};
|
|
HKEY hKey;
|
|
LPTSTR lpSubKey;
|
|
DWORD pdwSizeRequired[REG_UPDATE_FIELD_COUNT+1] = {0,MAX_PATH,0,0,0,0};
|
|
int i;
|
|
|
|
//check the INF file handle
|
|
if(hInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!lpszUsersid || !MyStrCmpI(lpszUsersid,TEXT("Default_User_SID")))
|
|
{
|
|
//If user sid is NULL it means default user
|
|
cChSecBuffeSize = lstrlen(TEXT("REG.Update.Default User")) + 1 ;
|
|
lpszSectionSuffix = DEFAULT_USER;
|
|
}
|
|
else if (!lpszUsersid[0])
|
|
{
|
|
//If user sid is "", it means system wide regsitry
|
|
cChSecBuffeSize = lstrlen(TEXT("REG.Update.Sys")) + 1 ;
|
|
lpszSectionSuffix = TEXT("SYS");
|
|
} else
|
|
{
|
|
//If it's normal user , the section name is "REG.Update.%userSID%"
|
|
|
|
cChSecBuffeSize = lstrlen(TEXT("REG.Update.")) + lstrlen(lpszUsersid)+2;
|
|
}
|
|
|
|
//Alloc memory and contruct the section name
|
|
if (!(lpszSectionName = (LPTSTR) malloc(cChSecBuffeSize * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
if (lpszSectionSuffix)
|
|
{
|
|
if (FAILED(StringCchPrintf(lpszSectionName,cChSecBuffeSize,TEXT("%s%s"),TEXT("REG.Update."),
|
|
lpszSectionSuffix)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FAILED(StringCchPrintf(lpszSectionName,cChSecBuffeSize,TEXT("%s%s"),TEXT("REG.Update."),
|
|
lpszUsersid)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
//here we got the section name and then try to get how many lines there
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpszSectionName);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
//BUGBUG: xiaoz:The error value here needs to be revisted
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//Scan the INF file section to get the max buf required for each field
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
DWORD dwNumField;
|
|
DWORD dwDataStart;
|
|
if (!SetupGetLineByIndex(hInf,lpszSectionName,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
|
|
continue;
|
|
}
|
|
dwNumField = SetupGetFieldCount(&InfContext);
|
|
if ( dwNumField < 4 )
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,lpszField[1],pdwSizeRequired[1],NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
|
|
continue;
|
|
}
|
|
dwRegUpdateType = _tstoi(lpszField[1]);
|
|
switch (dwRegUpdateType)
|
|
{
|
|
case CONSTANT_REG_VALUE_DATA_RENAME:
|
|
if (!SetupGetStringField(&InfContext,2,szStrType,ARRAYSIZE(szStrType),NULL))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
|
|
continue;
|
|
}
|
|
dwStrType = _tstoi(szStrType);
|
|
dwDataStart = 3;
|
|
break;
|
|
case CONSTANT_REG_VALUE_NAME_RENAME:
|
|
case CONSTANT_REG_KEY_RENAME:
|
|
dwDataStart = 2;
|
|
break;
|
|
}
|
|
for (nFieldIndex = dwDataStart ; nFieldIndex <= min(dwNumField,REG_UPDATE_FIELD_COUNT) ; nFieldIndex++)
|
|
{
|
|
BOOL bRet;
|
|
DWORD cchReqSize;
|
|
if ((nFieldIndex == REG_UPDATE_FIELD_COUNT) && (dwStrType == REG_MULTI_SZ))
|
|
{
|
|
bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
|
|
}
|
|
else
|
|
{
|
|
bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
|
|
}
|
|
if (!bRet)
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
|
|
continue;
|
|
}
|
|
pdwSizeRequired[nFieldIndex] = max(pdwSizeRequired[nFieldIndex],cchReqSize);
|
|
}
|
|
}
|
|
|
|
for (i = 2; i<= REG_UPDATE_FIELD_COUNT; i++)
|
|
{
|
|
if (pdwSizeRequired[i])
|
|
{
|
|
if ( NULL == (lpszField[i] = malloc(++pdwSizeRequired[i] * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
for(LineNo=0; LineNo<LineCount; LineNo++)
|
|
{
|
|
SetupGetLineByIndex(hInf,lpszSectionName,LineNo,&InfContext);
|
|
SetupGetStringField(&InfContext,1,lpszField[1],pdwSizeRequired[1],NULL);
|
|
dwRegUpdateType = _tstoi(lpszField[1]);
|
|
switch (dwRegUpdateType)
|
|
{
|
|
case CONSTANT_REG_VALUE_DATA_RENAME:
|
|
SetupGetStringField(&InfContext,2,szStrType,ARRAYSIZE(szStrType),NULL);
|
|
dwStrType = _tstoi(szStrType);
|
|
SetupGetStringField(&InfContext,3,lpszField[3],pdwSizeRequired[3],NULL);
|
|
SetupGetStringField(&InfContext,4,lpszField[4],pdwSizeRequired[4],NULL);
|
|
|
|
if ((dwStrType & 0xffff) == REG_MULTI_SZ)
|
|
{
|
|
SetupGetMultiSzField(&InfContext,5,lpszField[5],pdwSizeRequired[5],NULL);
|
|
}
|
|
else if ((dwStrType & 0xffff) == REG_BINARY)
|
|
{
|
|
if (!SetupGetBinaryField(&InfContext,5,(LPBYTE)lpszField[5],pdwSizeRequired[5]*sizeof(TCHAR),&dwRequestSize) &&
|
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
free(lpszField[5]);
|
|
if ((lpszField[5] = (LPTSTR)malloc(dwRequestSize)) == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
SetupGetBinaryField(&InfContext,5,(LPBYTE)lpszField[5],dwRequestSize,NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetupGetStringField(&InfContext,5,lpszField[5],pdwSizeRequired[5],NULL);
|
|
}
|
|
|
|
if (!(*lpszField[3]))
|
|
{
|
|
lpSubKey = NULL;
|
|
}
|
|
else
|
|
{
|
|
Str2KeyPath(lpszField[3],&hKey,&lpSubKey);
|
|
}
|
|
if (hKeyUser)
|
|
{
|
|
hKey = hKeyUser;
|
|
}
|
|
if ( (dwStrType & 0xffff) == REG_DWORD)
|
|
{
|
|
MyRegSetDWValue(hKey,lpSubKey,lpszField[4],lpszField[5]);
|
|
}
|
|
else
|
|
{
|
|
RegResetValue(hKey,lpSubKey,lpszField[4],dwStrType,TEXT(""),lpszField[5],dwRequestSize,lpszUsersid);
|
|
}
|
|
break;
|
|
case CONSTANT_REG_VALUE_NAME_RENAME:
|
|
case CONSTANT_REG_KEY_RENAME:
|
|
for (i = 2; i <= 4 ;i++)
|
|
{
|
|
SetupGetStringField(&InfContext,i,lpszField[i],pdwSizeRequired[i],NULL);
|
|
}
|
|
Str2KeyPath(lpszField[2],&hKey,&lpSubKey);
|
|
if (hKeyUser)
|
|
{
|
|
hKey = hKeyUser;
|
|
}
|
|
if (dwRegUpdateType == CONSTANT_REG_VALUE_NAME_RENAME)
|
|
{
|
|
RegResetValueName(hKey,lpSubKey,lpszField[3],lpszField[4], lpszUsersid);
|
|
}
|
|
else
|
|
{
|
|
RegResetKeyName(hKey, lpSubKey, lpszField[3], lpszField[4]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Cleanup:
|
|
FreePointer(lpszSectionName);
|
|
for (i = 2; i< ARRAYSIZE(lpszField); i++)
|
|
{
|
|
FreePointer(lpszField[i]);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT INFCreateHardLink(
|
|
HINF hInf,
|
|
LPTSTR lpszSection,
|
|
BOOL bMakeLinkHidden)
|
|
{
|
|
HRESULT hr;
|
|
INT LineCount,LineNo,nFieldIndex;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szFileName[MAX_PATH+1],szExistingFileName[MAX_PATH+1],szHidden[MAX_PATH];
|
|
TCHAR szType[10];
|
|
DWORD dwType;
|
|
TCHAR lpszInf[MAX_PATH+1];
|
|
HINF hMyInf;
|
|
BOOL bLocalHidden = bMakeLinkHidden;
|
|
|
|
//check the INF file handle
|
|
hMyInf = hInf;
|
|
if(hMyInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = EnsureDoItemInfFile(lpszInf,ARRAYSIZE(lpszInf));
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
hMyInf = SetupOpenInfFile(lpszInf,
|
|
NULL,
|
|
INF_STYLE_WIN4,
|
|
NULL);
|
|
if (hMyInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
LineCount = (UINT)SetupGetLineCount(hMyInf,lpszSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
for (LineNo = LineCount -1 ; LineNo >= 0; LineNo--)
|
|
{
|
|
BOOL b1,b2,b3,b4;
|
|
|
|
if (!SetupGetLineByIndex(hMyInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
continue;
|
|
}
|
|
b1 = SetupGetStringField(&InfContext,1,szType,ARRAYSIZE(szType),NULL);
|
|
b2 = SetupGetStringField(&InfContext,2,szFileName,ARRAYSIZE(szFileName),NULL);
|
|
b3 = SetupGetStringField(&InfContext,3,szExistingFileName,ARRAYSIZE(szExistingFileName),NULL);
|
|
if (!b1 || !b2 || !b3)
|
|
{
|
|
continue;
|
|
}
|
|
b4 = SetupGetStringField(&InfContext,4,szHidden,ARRAYSIZE(szHidden),NULL);
|
|
|
|
bLocalHidden = bMakeLinkHidden;
|
|
if (b4)
|
|
{
|
|
DWORD dwHiddenType;
|
|
|
|
dwHiddenType = _tstoi(szHidden);
|
|
if (!dwHiddenType)
|
|
{
|
|
bLocalHidden = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bLocalHidden = TRUE;
|
|
}
|
|
}
|
|
dwType = _tstoi(szType);
|
|
#ifdef CREATE_MINI_HARDLIN
|
|
if (g_dwRunningStatus == CLMT_CURE_PROGRAM_FILES)
|
|
{
|
|
if (dwType == 0)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef CONSOLE_UI
|
|
wprintf(TEXT("create reparse point between folder %s and %s\n"),szFileName,szExistingFileName);
|
|
#endif
|
|
|
|
if (CreateSymbolicLink(szFileName,szExistingFileName,bLocalHidden))
|
|
{
|
|
//hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
//hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if ( (hInf == INVALID_HANDLE_VALUE) && (hMyInf != INVALID_HANDLE_VALUE) )
|
|
{
|
|
SetupCloseInfFile(hMyInf);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// Function: AnalyzeServicesStatus
|
|
//
|
|
// Descrip: Analyze the services running on the system and see if
|
|
// they need to be stopped or not
|
|
//
|
|
// Returns: S_OK if function succeeded.
|
|
// else if error occured
|
|
//
|
|
// Notes: none
|
|
//
|
|
// History: 04/30/2002 rerkboos created
|
|
// 07/08/2002 rerkboos modified
|
|
// 09/06/2002 rerkboos modified
|
|
//
|
|
// Notes: Format of the section in clmt.inf:
|
|
// <service name to be stopped>, <action>
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
HRESULT AnalyzeServicesStatus(
|
|
HINF hInf, // Handle to Migration INF
|
|
LPCTSTR lpInfSection // Section to be read from INF
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet = TRUE;
|
|
LONG lLineCount;
|
|
LONG lLineIndex;
|
|
INFCONTEXT context;
|
|
TCHAR szServiceName[128];
|
|
TCHAR szControl[8];
|
|
TCHAR szCleanupControl[8];
|
|
INT iRunningStatus;
|
|
INT iServiceControl;
|
|
DWORD dwCleanupControl;
|
|
SC_HANDLE schService;
|
|
SC_HANDLE schSCManager;
|
|
SERVICE_STATUS ssStatus;
|
|
|
|
if (hInf == INVALID_HANDLE_VALUE || lpInfSection == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
if (schSCManager != NULL)
|
|
{
|
|
// Read the list of services to be reset from INF
|
|
lLineCount = SetupGetLineCount(hInf, lpInfSection);
|
|
for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
|
|
{
|
|
bRet = SetupGetLineByIndex(hInf,
|
|
lpInfSection,
|
|
(DWORD) lLineIndex,
|
|
&context);
|
|
if (bRet)
|
|
{
|
|
bRet = SetupGetStringField(&context,
|
|
1,
|
|
szServiceName,
|
|
ARRAYSIZE(szServiceName),
|
|
NULL)
|
|
&& SetupGetIntField(&context,
|
|
2,
|
|
&iRunningStatus)
|
|
&& SetupGetIntField(&context,
|
|
3,
|
|
&iServiceControl);
|
|
if (bRet)
|
|
{
|
|
schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
|
|
if (schService != NULL)
|
|
{
|
|
QueryServiceStatus(schService, &ssStatus);
|
|
if (ssStatus.dwCurrentState == (DWORD) iRunningStatus)
|
|
{
|
|
switch (iServiceControl)
|
|
{
|
|
case SERVICE_CONTROL_STOP:
|
|
dwCleanupControl = 0; // 0 means start the service
|
|
break;
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
dwCleanupControl = SERVICE_CONTROL_CONTINUE;
|
|
break;
|
|
}
|
|
|
|
_itot(iServiceControl, szControl, 10);
|
|
_ultot(dwCleanupControl, szCleanupControl, 10);
|
|
|
|
WritePrivateProfileString(TEXT_SERVICE_STATUS_SECTION,
|
|
szServiceName,
|
|
szControl,
|
|
g_szToDoINFFileName);
|
|
|
|
WritePrivateProfileString(TEXT_SERVICE_STATUS_CLEANUP_SECTION,
|
|
szServiceName,
|
|
szCleanupControl,
|
|
g_szToDoINFFileName);
|
|
}
|
|
|
|
CloseServiceHandle(schService);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// Function: AnalyzeServicesStartUp
|
|
//
|
|
// Descrip: Analyze services startup type. Some components in the system
|
|
// need to be stopped and not to start automatically until
|
|
// upgraded to .NET server. So, we might need to change those
|
|
// services to "Manually Start".
|
|
// 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
|
|
//
|
|
// Returns: S_OK if function succeeded.
|
|
// else if error occured
|
|
//
|
|
// Notes: none
|
|
//
|
|
// History: 09/07/2002 rerkboos created
|
|
//
|
|
// Notes: Format of the section in clmt.inf:
|
|
// <service name>, <current start type in system>, <new start type>
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
HRESULT AnalyzeServicesStartUp(
|
|
HINF hInf,
|
|
LPCTSTR lpInfSection
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet = TRUE;
|
|
LONG lLineCount;
|
|
LONG lLineIndex;
|
|
INFCONTEXT context;
|
|
WCHAR szServiceName[64];
|
|
WCHAR szCurrentStartupType[8];
|
|
WCHAR szNewStartupType[8];
|
|
INT iCurrentStartupType;
|
|
INT iNewStartupType;
|
|
DWORD dwBytesNeeded;
|
|
SC_HANDLE schService;
|
|
SC_HANDLE schSCManager;
|
|
SERVICE_STATUS ssStatus;
|
|
LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
|
|
|
|
if (hInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
if (schSCManager != NULL)
|
|
{
|
|
lLineCount = SetupGetLineCount(hInf, lpInfSection);
|
|
for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
|
|
{
|
|
bRet = SetupGetLineByIndex(hInf,
|
|
lpInfSection,
|
|
(DWORD) lLineIndex,
|
|
&context);
|
|
if (bRet)
|
|
{
|
|
bRet = SetupGetStringField(&context,
|
|
1,
|
|
szServiceName,
|
|
ARRAYSIZE(szServiceName),
|
|
NULL)
|
|
&& SetupGetIntField(&context,
|
|
2,
|
|
&iCurrentStartupType)
|
|
&& SetupGetIntField(&context,
|
|
3,
|
|
&iNewStartupType);
|
|
if (bRet)
|
|
{
|
|
schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_CONFIG);
|
|
if (schService != NULL)
|
|
{
|
|
lpqscBuf = (LPQUERY_SERVICE_CONFIG) MEMALLOC(4096);
|
|
if (lpqscBuf != NULL)
|
|
{
|
|
bRet = QueryServiceConfig(schService,
|
|
lpqscBuf,
|
|
4096,
|
|
&dwBytesNeeded);
|
|
if (bRet)
|
|
{
|
|
if (lpqscBuf->dwStartType == (DWORD) iCurrentStartupType)
|
|
{
|
|
_itot(iCurrentStartupType, szCurrentStartupType, 10);
|
|
_itot(iNewStartupType, szNewStartupType, 10);
|
|
|
|
WritePrivateProfileString(TEXT_SERVICE_STARTUP_SECTION,
|
|
szServiceName,
|
|
szNewStartupType,
|
|
g_szToDoINFFileName);
|
|
WritePrivateProfileString(TEXT_SERVICE_STARTUP_CLEANUP_SECTION,
|
|
szServiceName,
|
|
szCurrentStartupType,
|
|
g_szToDoINFFileName);
|
|
}
|
|
}
|
|
|
|
MEMFREE(lpqscBuf);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
CloseServiceHandle(schService);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// Function: ResetServicesStatus
|
|
//
|
|
// Descrip: Reset the services listed in specified section of INF
|
|
//
|
|
// Returns: S_OK if function succeeded.
|
|
// else if error occured
|
|
//
|
|
// Notes: none
|
|
//
|
|
// History: 04/30/2002 rerkboos created
|
|
// 07/08/2002 rerkboos modified
|
|
//
|
|
// Notes: Format of the section in clmt.inf:
|
|
// <service name to be stopped>, <action>
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
HRESULT ResetServicesStatus(
|
|
HINF hInf, // Handle to INF
|
|
LPCTSTR lpInfSection // Section to be read from INF
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet = TRUE;
|
|
LONG lLineCount;
|
|
LONG lLineIndex;
|
|
INFCONTEXT context;
|
|
WCHAR szServiceName[128];
|
|
INT iServiceControl;
|
|
|
|
if (hInf == INVALID_HANDLE_VALUE || lpInfSection == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Read the list of services to be reset from INF
|
|
lLineCount = SetupGetLineCount(hInf, lpInfSection);
|
|
for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
|
|
{
|
|
bRet = SetupGetLineByIndex(hInf,
|
|
lpInfSection,
|
|
(DWORD) lLineIndex,
|
|
&context);
|
|
if (bRet)
|
|
{
|
|
bRet = SetupGetStringField(&context,
|
|
0,
|
|
szServiceName,
|
|
ARRAYSIZE(szServiceName),
|
|
NULL)
|
|
&& SetupGetIntField(&context,
|
|
1,
|
|
&iServiceControl);
|
|
if (bRet)
|
|
{
|
|
hr = ResetServiceStatus(szServiceName,
|
|
(DWORD) iServiceControl,
|
|
10);
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// Function: ResetServicesStartUp
|
|
//
|
|
// Descrip: Reconfigure services start type. Some components in the system
|
|
// need to be stopped and not to start automatically until
|
|
// upgraded to .NET server. So, we might need to change those
|
|
// services to "Manually Start".
|
|
// 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
|
|
//
|
|
// Returns: S_OK if function succeeded.
|
|
// else if error occured
|
|
//
|
|
// Notes: none
|
|
//
|
|
// History: 04/30/2002 rerkboos created
|
|
//
|
|
// Notes: Format of the section in clmt.inf:
|
|
// <service name>, <current start type in system>, <new start type>
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
HRESULT ResetServicesStartUp(
|
|
HINF hInf,
|
|
LPCTSTR lpInfSection
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet = TRUE;
|
|
LONG lLineCount;
|
|
LONG lLineIndex;
|
|
INFCONTEXT context;
|
|
WCHAR szServiceName[64];
|
|
INT iNewStartupType;
|
|
|
|
if (hInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
lLineCount = SetupGetLineCount(hInf, lpInfSection);
|
|
for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
|
|
{
|
|
bRet = SetupGetLineByIndex(hInf,
|
|
lpInfSection,
|
|
(DWORD) lLineIndex,
|
|
&context);
|
|
if (bRet)
|
|
{
|
|
bRet = SetupGetStringField(&context,
|
|
0,
|
|
szServiceName,
|
|
ARRAYSIZE(szServiceName),
|
|
NULL)
|
|
&& SetupGetIntField(&context,
|
|
1,
|
|
&iNewStartupType);
|
|
if (bRet)
|
|
{
|
|
hr = ChangeServiceStartupType(szServiceName,
|
|
iNewStartupType,
|
|
10);
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT ChangeServiceStartupType(
|
|
LPCTSTR lpServiceName,
|
|
DWORD dwNewStartupType,
|
|
DWORD dwMaxWait
|
|
)
|
|
{
|
|
SC_LOCK sclLock = NULL;
|
|
SERVICE_DESCRIPTION sdBuf;
|
|
DWORD dwBytesNeeded;
|
|
DWORD dwStartType;
|
|
SC_HANDLE schSCManager = NULL;
|
|
SC_HANDLE schService = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwCnt;
|
|
BOOL bRet;
|
|
|
|
if (lpServiceName == NULL)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
schSCManager = OpenSCManager(NULL, // machine (NULL == local)
|
|
NULL, // database (NULL == default)
|
|
SC_MANAGER_ALL_ACCESS);
|
|
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 != NULL)
|
|
{
|
|
// The database is locked, so it is safe to make changes.
|
|
// Open a handle to the service.
|
|
schService = OpenService(schSCManager, // SCManager database
|
|
lpServiceName, // name of service
|
|
SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG );
|
|
if (schService != NULL)
|
|
{
|
|
// Make the changes
|
|
bRet = ChangeServiceConfig(schService, // handle of service
|
|
SERVICE_NO_CHANGE, // service type: no change
|
|
dwNewStartupType, // 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
|
|
if (!bRet)
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
CloseServiceHandle(schService);
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
UnlockServiceDatabase(sclLock);
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
cleanup:
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
if (schSCManager)
|
|
{
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
BOOL LnkFileUpdate(LPTSTR lpszFile)
|
|
{
|
|
HRESULT hr ;
|
|
hr = AddNeedUpdateLnkFile(lpszFile,&g_StrReplaceTable );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL SecTempUpdate(LPTSTR lpszFile)
|
|
{
|
|
HRESULT hr ;
|
|
hr = UpdateSecurityTemplates(lpszFile,&g_StrReplaceTable );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
// Function: ResetServiceStatus
|
|
//
|
|
// Descrip: Reset the running (start/pause/stop) status of
|
|
// the specified service
|
|
//
|
|
// Returns: S_OK if function succeeded.
|
|
// else if error occured
|
|
//
|
|
// Notes: none
|
|
//
|
|
// History: 07/09/2002 rerkboos created
|
|
//
|
|
// Notes: Format of the section in clmt.inf:
|
|
// <service name>, <control>
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
HRESULT ResetServiceStatus(
|
|
LPCTSTR lpServiceName, // Service name
|
|
DWORD dwControl, // Control for the specified service
|
|
DWORD dwMaxWait // Timeout in seconds
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
BOOL bRet = FALSE;
|
|
SC_HANDLE schService;
|
|
SC_HANDLE schSCManager;
|
|
SERVICE_STATUS ssStatus;
|
|
DWORD dwSec;
|
|
DWORD dwFinalStatus;
|
|
|
|
switch (dwControl)
|
|
{
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
dwFinalStatus = SERVICE_RUNNING;
|
|
break;
|
|
|
|
case SERVICE_CONTROL_PAUSE:
|
|
dwFinalStatus = SERVICE_PAUSED;
|
|
break;
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
dwFinalStatus = SERVICE_STOPPED;
|
|
break;
|
|
|
|
case 0: // Start service
|
|
dwFinalStatus = SERVICE_RUNNING;
|
|
break;
|
|
}
|
|
|
|
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
if (schSCManager != NULL)
|
|
{
|
|
schService = OpenService(schSCManager, lpServiceName, SERVICE_ALL_ACCESS);
|
|
if (schService != NULL)
|
|
{
|
|
if (dwControl == 0)
|
|
{
|
|
// Start service
|
|
bRet = StartService(schService, 0, NULL);
|
|
}
|
|
else
|
|
{
|
|
// Continue, Pause, Stop service
|
|
bRet = ControlService(schService, dwControl, &ssStatus);
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
dwSec = 0;
|
|
hr = S_FALSE;
|
|
|
|
while (QueryServiceStatus(schService, &ssStatus)
|
|
&& dwSec < dwMaxWait)
|
|
{
|
|
if (ssStatus.dwCurrentState != dwFinalStatus)
|
|
{
|
|
Sleep(1000);
|
|
dwSec++;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
DPF(APPwar,
|
|
TEXT(" Warning! - [%s] service status cannot change from %d to %d\n"),
|
|
lpServiceName,
|
|
ssStatus.dwCurrentState,
|
|
dwFinalStatus);
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle(schService);
|
|
}
|
|
|
|
CloseServiceHandle(schSCManager);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT FinalUpdateRegForUser(HKEY hKeyUser,
|
|
LPTSTR UserName,
|
|
LPTSTR DomainName,
|
|
LPTSTR UserSid)
|
|
{
|
|
RegUpdate(g_hInfDoItem, hKeyUser, UserSid);
|
|
return S_OK;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does the per user registry search and replace, the string replace table
|
|
is in global variable g_StrReplaceTable
|
|
|
|
Arguments:
|
|
|
|
hKeyUser - user registry key handle
|
|
UserName - user name that hKeyUser belongs to
|
|
DomainName - domain name the UserName belongs to
|
|
Return Value:
|
|
|
|
NULL
|
|
--*/
|
|
HRESULT UpdateRegPerUser (HKEY hKeyUser,
|
|
LPTSTR UserName,
|
|
LPTSTR DomainName,
|
|
LPTSTR UserSid)
|
|
{
|
|
return RegistryAnalyze(hKeyUser,UserName,UserSid,&g_StrReplaceTable,NULL,0,NULL,TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT UpdateDSObjProp(
|
|
HINF hInf,
|
|
LPTSTR lpInfSection)
|
|
{
|
|
#define DSOBJNUMOFFIELD 3
|
|
DWORD dwFileValid[DSOBJNUMOFFIELD] = {1,1,1};
|
|
DWORD arrSizeNeeded[DSOBJNUMOFFIELD];
|
|
LPTSTR lpField[DSOBJNUMOFFIELD];
|
|
UINT LineCount,LineNo;
|
|
INFCONTEXT InfContext;
|
|
HRESULT hr;
|
|
int i;
|
|
|
|
for ( i = 0; i < DSOBJNUMOFFIELD; i++)
|
|
{
|
|
lpField[i] = NULL;
|
|
}
|
|
hr = GetMaxLenEachField(hInf,lpInfSection,FALSE,DSOBJNUMOFFIELD,DSOBJNUMOFFIELD,
|
|
(PDWORD)dwFileValid,arrSizeNeeded,FALSE);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
for (i = 0; i < DSOBJNUMOFFIELD; i++)
|
|
{
|
|
if (!(lpField[i] = malloc(arrSizeNeeded[i]*sizeof(TCHAR))))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpInfSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
//Scan the INF file section to get the max buf required for each field
|
|
for (LineNo = 0; LineNo < LineCount; LineNo++)
|
|
{
|
|
if (!SetupGetLineByIndex(hInf,lpInfSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpInfSection);
|
|
continue;
|
|
}
|
|
for (i = 1; i <= DSOBJNUMOFFIELD; i++)
|
|
{
|
|
SetupGetStringField(&InfContext,i,lpField[i-1],arrSizeNeeded[i-1],NULL);
|
|
}
|
|
PropertyValueHelper( lpField[0],lpField[1],NULL,lpField[2]);
|
|
}
|
|
hr =S_OK;
|
|
cleanup:
|
|
for (i = 0; i < DSOBJNUMOFFIELD; i++)
|
|
{
|
|
FreePointer(lpField[i]);
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DoServicesAnalyze()
|
|
{
|
|
AnalyzeServicesStatus(g_hInf, TEXT_SERVICE_STATUS_SECTION);
|
|
AnalyzeServicesStartUp(g_hInf, TEXT_SERVICE_STARTUP_SECTION);
|
|
}
|
|
|
|
|
|
|
|
HRESULT INFVerifyHardLink(
|
|
HINF hInf,
|
|
LPTSTR lpszSection)
|
|
{
|
|
HRESULT hr;
|
|
INT LineCount,LineNo,nFieldIndex;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szFileName[MAX_PATH+1],szExistingFileName[MAX_PATH+1],szCurrLink[MAX_PATH];
|
|
TCHAR lpszInf[MAX_PATH+1];
|
|
HINF hMyInf;
|
|
|
|
//check the INF file handle
|
|
hMyInf = hInf;
|
|
if(hMyInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = EnsureDoItemInfFile(lpszInf,ARRAYSIZE(lpszInf));
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
hMyInf = SetupOpenInfFile(lpszInf,
|
|
NULL,
|
|
INF_STYLE_WIN4,
|
|
NULL);
|
|
if (hMyInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
LineCount = (UINT)SetupGetLineCount(hMyInf,lpszSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
for (LineNo = 0 ; LineNo < LineCount; LineNo++)
|
|
{
|
|
BOOL b1,b2,b3,b4;
|
|
|
|
if (!SetupGetLineByIndex(hMyInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
continue;
|
|
}
|
|
b2 = SetupGetStringField(&InfContext,2,szFileName,ARRAYSIZE(szFileName),NULL);
|
|
b3 = SetupGetStringField(&InfContext,3,szExistingFileName,ARRAYSIZE(szExistingFileName),NULL);
|
|
if (!b2 || !b3)
|
|
{
|
|
continue;
|
|
}
|
|
if (GetSymbolicLink(szFileName,szCurrLink,ARRAYSIZE(szCurrLink)))
|
|
{
|
|
if (!IsDirExisting(szCurrLink))
|
|
{
|
|
RemoveDirectory(szFileName);
|
|
}
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if ( (hInf == INVALID_HANDLE_VALUE) && (hMyInf != INVALID_HANDLE_VALUE) )
|
|
{
|
|
SetupCloseInfFile(hMyInf);
|
|
}
|
|
return hr;
|
|
}
|