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.
1454 lines
44 KiB
1454 lines
44 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
utils2.c
|
|
|
|
Abstract:
|
|
|
|
utillities to update lnk/msi/... file
|
|
|
|
Author:
|
|
|
|
Xiaofeng Zang (xiaoz) 08-Oct-2001 Created
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
#define NOT_USE_SAFE_STRING
|
|
#include "clmt.h"
|
|
#include <objbase.h>
|
|
#include <shellapi.h>
|
|
#include <shlguid.h>
|
|
#include <comdef.h>
|
|
#include <iads.h>
|
|
#include <adsiid.h>
|
|
#include <adshlp.h>
|
|
#define STRSAFE_LIB
|
|
#include <strsafe.h>
|
|
|
|
|
|
class CServiceHandle
|
|
{
|
|
public :
|
|
CServiceHandle() { _h = 0; }
|
|
CServiceHandle( SC_HANDLE hSC ) : _h( hSC ) {}
|
|
~CServiceHandle() { Free(); }
|
|
void Set( SC_HANDLE h ) { _h = h; }
|
|
SC_HANDLE Get() { return _h; }
|
|
BOOL IsNull() { return ( 0 == _h ); }
|
|
void Free() { if ( 0 != _h ) CloseServiceHandle( _h ); _h = 0; }
|
|
private:
|
|
SC_HANDLE _h;
|
|
};
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: IsServiceRunning
|
|
//
|
|
// Synopsis: Determines if a service is running
|
|
//
|
|
// Arguments: pwcServiceName -- The name (short or long) of the service
|
|
//
|
|
// Returns: TRUE if the service is running, FALSE otherwise or if the
|
|
// system is low on resources or the status can't be queried.
|
|
//
|
|
// History: 3/22/2002 geoffguo Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOL IsServiceRunning(LPCTSTR pwcServiceName)
|
|
{
|
|
CServiceHandle xhSC( OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ) );
|
|
if ( xhSC.IsNull() )
|
|
return FALSE;
|
|
|
|
CServiceHandle xhService( OpenService( xhSC.Get(),
|
|
pwcServiceName,
|
|
SERVICE_QUERY_STATUS ) );
|
|
if ( xhSC.IsNull() )
|
|
return FALSE;
|
|
|
|
SERVICE_STATUS svcStatus;
|
|
if ( QueryServiceStatus( xhService.Get(), &svcStatus ) )
|
|
return ( SERVICE_RUNNING == svcStatus.dwCurrentState );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT AddNeedUpdateLnkFile(
|
|
LPTSTR pszShortcutFile,
|
|
PREG_STRING_REPLACE lpStrList)
|
|
{
|
|
HRESULT hr;
|
|
IShellLink *psl = NULL;
|
|
TCHAR szGotPath [MAX_PATH];
|
|
TCHAR szNewPath [2*MAX_PATH];
|
|
TCHAR szArg[INFOTIPSIZE+1],szNewArg[2*INFOTIPSIZE+1];
|
|
WIN32_FIND_DATA wfd;
|
|
IPersistFile *ppf = NULL;
|
|
int nIcon;
|
|
LPTSTR lpszOneline = NULL;
|
|
size_t cchOneline = 0;
|
|
TCHAR szIndex[MAX_PATH];
|
|
LPTSTR lpszAppend = TEXT("");
|
|
BOOL bLnkUpdated = FALSE;
|
|
BOOL bTargetGot = FALSE;
|
|
BOOL bTargetUpdated = FALSE;
|
|
DWORD dwAttrib;
|
|
LPTSTR lpszStrWithExtraQuote;
|
|
|
|
if (!pszShortcutFile || !pszShortcutFile[0] || !lpStrList)
|
|
{
|
|
hr = S_FALSE;
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: InValid Parameter(s)"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//Allocate memory for "LnkFile,TargetPath,IconPath,Working Dir,Relative Path and Argument"
|
|
cchOneline = lstrlen(pszShortcutFile) + 5 * MAX_PATH + INFOTIPSIZE+1;
|
|
if (!(lpszOneline = (LPTSTR)malloc(cchOneline * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
// Get a pointer to the IShellLink interface.
|
|
hr = CoCreateInstance (CLSID_ShellLink,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IShellLink,
|
|
(void **)&psl);
|
|
|
|
if (FAILED (hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: CoCreateInstance CLSID_ShellLink return %d (%#x)\n"), hr, hr);
|
|
goto Cleanup;
|
|
}
|
|
// Get a pointer to the IPersistFile interface.
|
|
hr = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: QueryInterface IID_IPersistFile return %d (%#x)\n"), hr, hr);
|
|
goto Cleanup;
|
|
}
|
|
// Load the shortcut.
|
|
hr = ppf->Load (pszShortcutFile, STGM_READWRITE );
|
|
if (FAILED(hr))
|
|
{
|
|
hr = S_FALSE;
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: can not load shortcut file %s"),pszShortcutFile);
|
|
goto Cleanup;
|
|
}
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("\"%s\""),pszShortcutFile);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer lpszOneline is too small for %s"),pszShortcutFile);
|
|
goto Cleanup;
|
|
}
|
|
// Get the path to the shortcut target.
|
|
hr = psl->GetPath (szGotPath,
|
|
ARRAYSIZE(szGotPath),
|
|
(WIN32_FIND_DATA *)&wfd,
|
|
SLGP_RAWPATH);
|
|
|
|
if (SUCCEEDED (hr))
|
|
{ //Succeeded get the target
|
|
DWORD dwNum ;
|
|
DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetPath %s OK "), szGotPath);
|
|
//Set bTargetGot so that it cab be used to set relative target path
|
|
bTargetGot = TRUE;
|
|
|
|
//szGotPath contains LNK's target path, if dwNum >0 , it means szGotPath
|
|
//contains (localized) path that we renamed
|
|
dwNum = GetMaxMatchNum(szGotPath,lpStrList);
|
|
|
|
//call ReplaceMultiMatchInString ,to replace szGotPath's localized folder
|
|
//with english one, and put new path in szNewPath
|
|
if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
lpszAppend = szNewPath;
|
|
bTargetUpdated = TRUE;
|
|
bLnkUpdated = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetPath %s Error = %d"), szGotPath,hr);
|
|
}
|
|
if (MyStrCmpI(lpszAppend,TEXT("")))
|
|
{
|
|
hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lpszStrWithExtraQuote)
|
|
{
|
|
lpszAppend = lpszStrWithExtraQuote;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszStrWithExtraQuote = NULL;
|
|
}
|
|
//Append the new quoted target path to lpszOneline
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
|
|
FreePointer(lpszStrWithExtraQuote);
|
|
//check StringCchPrintf here, because we want to free lpszStrWithExtraQuote before
|
|
//we do a jump (if necessary)
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer lpszOneline is too small for %s"),lpszAppend);
|
|
goto Cleanup;
|
|
}
|
|
|
|
//if we arrive here , we have succeeded in appeneding target to the lszOneline
|
|
//we will update relative target path ,which is relative to where the current
|
|
//lnk resides
|
|
lpszAppend = TEXT("");
|
|
if (bTargetGot) //this means we succeeded get the target path
|
|
{
|
|
DWORD dwNum ;
|
|
//szNewLnkFilePath is the lnk full path with localized folder renamed to english one(if any)
|
|
TCHAR szNewLnkFilePath[2*MAX_PATH],szCurrTarget[2*MAX_PATH];
|
|
TCHAR szExpandedCurrTarget[2*MAX_PATH];
|
|
TCHAR szNewTarget[2*MAX_PATH];
|
|
|
|
//Check to see whether current pszShortcutFile resides a direcory that contains
|
|
//localized folder we renamed
|
|
dwNum = GetMaxMatchNum(pszShortcutFile,lpStrList);
|
|
if (dwNum)
|
|
{
|
|
if (!ReplaceMultiMatchInString(pszShortcutFile,szNewLnkFilePath,
|
|
ARRAYSIZE(szNewLnkFilePath),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
//szNewLnkFilePath now is full path with localized folder renamed to english one
|
|
//if we fail do ReplaceMultiMatchInString, just clone to szNewLnkFilePath
|
|
hr = StringCchCopy(szNewLnkFilePath,ARRAYSIZE(szNewLnkFilePath),pszShortcutFile);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewLnkFilePath is too small for %s"),pszShortcutFile);
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//If pszShortcutFile does not contains any localized folder we renamed,
|
|
//just clone to szNewLnkFilePath
|
|
hr = StringCchCopy(szNewLnkFilePath,ARRAYSIZE(szNewLnkFilePath),pszShortcutFile);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewLnkFilePath is too small for %s"),pszShortcutFile);
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (bTargetUpdated)
|
|
{
|
|
if (FAILED(hr = StringCchCopy(szCurrTarget,ARRAYSIZE(szCurrTarget),szNewPath)))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FAILED(hr = StringCchCopy(szCurrTarget,ARRAYSIZE(szCurrTarget),szGotPath)))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
//target may contains enviroment variable
|
|
if (!ExpandEnvironmentStrings(szCurrTarget,szExpandedCurrTarget,ARRAYSIZE(szExpandedCurrTarget)))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Cleanup;
|
|
}
|
|
//Check whether target contains the folder we renamed
|
|
dwNum = GetMaxMatchNum(szExpandedCurrTarget,lpStrList);
|
|
if (dwNum)
|
|
{
|
|
if (!ReplaceMultiMatchInString(szExpandedCurrTarget,szNewTarget,ARRAYSIZE(szNewTarget),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
hr = StringCchCopy(szNewTarget,ARRAYSIZE(szNewTarget),szExpandedCurrTarget);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewTarget is too small for %s"),szExpandedCurrTarget);
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopy(szNewTarget,ARRAYSIZE(szNewTarget),szExpandedCurrTarget);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewTarget is too small for %s"),szExpandedCurrTarget);
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (PathRelativePathTo(szNewPath,szNewLnkFilePath,0,szNewTarget,0))
|
|
{
|
|
lpszAppend = szNewPath;
|
|
bLnkUpdated = TRUE;
|
|
}
|
|
}
|
|
if (MyStrCmpI(lpszAppend,TEXT("")))
|
|
{
|
|
hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lpszStrWithExtraQuote)
|
|
{
|
|
lpszAppend = lpszStrWithExtraQuote;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszStrWithExtraQuote = NULL;
|
|
}
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
|
|
FreePointer(lpszStrWithExtraQuote);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
lpszAppend = TEXT("");
|
|
hr = psl->GetIconLocation (szGotPath,ARRAYSIZE(szGotPath),&nIcon);
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
DWORD dwNum ;
|
|
DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetIconPath %s OK "), szGotPath);
|
|
dwNum = GetMaxMatchNum(szGotPath,lpStrList);
|
|
if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
lpszAppend = szNewPath;
|
|
bLnkUpdated = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetIconPath %s Error = %d"), szGotPath,hr);
|
|
}
|
|
if (MyStrCmpI(lpszAppend,TEXT("")))
|
|
{
|
|
hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lpszStrWithExtraQuote)
|
|
{
|
|
lpszAppend = lpszStrWithExtraQuote;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszStrWithExtraQuote = NULL;
|
|
}
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
|
|
FreePointer(lpszStrWithExtraQuote);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
lpszAppend = TEXT("");
|
|
hr = psl->GetWorkingDirectory (szGotPath,ARRAYSIZE(szGotPath));
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
DWORD dwNum ;
|
|
DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetWorkingDirPath %s OK "), szGotPath);
|
|
dwNum = GetMaxMatchNum(szGotPath,lpStrList);
|
|
if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
bLnkUpdated = TRUE;
|
|
lpszAppend = szNewPath;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetWorkingDirPath %s Error = %d"), szGotPath,hr);
|
|
}
|
|
if (MyStrCmpI(lpszAppend,TEXT("")))
|
|
{
|
|
hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lpszStrWithExtraQuote)
|
|
{
|
|
lpszAppend = lpszStrWithExtraQuote;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszStrWithExtraQuote = NULL;
|
|
}
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
|
|
FreePointer(lpszStrWithExtraQuote);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
lpszAppend = TEXT("");
|
|
hr = psl->GetArguments (szArg,ARRAYSIZE(szArg));
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
DWORD dwNum ;
|
|
DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetArguments %s OK "), szArg);
|
|
dwNum = GetMaxMatchNum(szArg,lpStrList);
|
|
if (dwNum && ReplaceMultiMatchInString(szArg,szNewArg,ARRAYSIZE(szNewArg),dwNum,lpStrList, &dwAttrib, TRUE))
|
|
{
|
|
bLnkUpdated = TRUE;
|
|
lpszAppend = szNewArg;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetArguments %s Error = %d"), pszShortcutFile,hr);
|
|
}
|
|
if (MyStrCmpI(lpszAppend,TEXT("")))
|
|
{
|
|
hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (lpszStrWithExtraQuote)
|
|
{
|
|
lpszAppend = lpszStrWithExtraQuote;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszStrWithExtraQuote = NULL;
|
|
}
|
|
hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
|
|
FreePointer(lpszStrWithExtraQuote);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (bLnkUpdated)
|
|
{
|
|
g_dwKeyIndex++;
|
|
_itot(g_dwKeyIndex,szIndex,16);
|
|
if (!WritePrivateProfileString(TEXT("LNK"),szIndex,lpszOneline,g_szToDoINFFileName))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
Cleanup:
|
|
if (psl)
|
|
{
|
|
psl->Release ();
|
|
}
|
|
if (ppf)
|
|
{
|
|
ppf->Release ();
|
|
}
|
|
FreePointer(lpszOneline);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT BatchFixPathInLink(
|
|
HINF hInf,
|
|
LPTSTR lpszSection)
|
|
{
|
|
HRESULT hr;
|
|
IShellLink *psl = NULL;
|
|
WIN32_FIND_DATA wfd;
|
|
IPersistFile *ppf = NULL;
|
|
int nIcon;
|
|
BOOL bSucceedOnce = FALSE;
|
|
UINT LineCount,LineNo;
|
|
INFCONTEXT InfContext;
|
|
LPTSTR lpszLnkFile = NULL,lpszPath = NULL,lpszIcon = NULL,lpszWorkingDir = NULL,
|
|
lpszRelPath = NULL,lpszArg = NULL;
|
|
DWORD cchMaxLnkFile = 0,cchMaxPath = 0,cchMaxIcon = 0,cchMaxWorkingDir = 0,
|
|
cchMaxRelPath = 0,cchMaxArg = 0;
|
|
DWORD dwFileAttrib;
|
|
BOOL bFileAttribChanged ;
|
|
|
|
|
|
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 cchTmpLnkFile = 0,cchTmpPath = 0,cchTmpIcon = 0,cchTmpWorkingDir = 0,
|
|
cchTmpRelPath = 0,cchTmpArg = 0;
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFerr ,TEXT("can not get line %n of section %s !"),LineNo, lpszSection);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,NULL,0,&cchTmpLnkFile))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 1 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpPath))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,3,NULL,0,&cchTmpRelPath))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 3 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!SetupGetStringField(&InfContext,4,NULL,0,&cchTmpIcon))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 4 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,5,NULL,0,&cchTmpWorkingDir))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 5 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,6,NULL,0,&cchTmpArg))
|
|
{
|
|
DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 6 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
cchMaxLnkFile = max(cchMaxLnkFile,cchTmpLnkFile);
|
|
cchMaxPath = max(cchMaxPath,cchTmpPath);
|
|
cchMaxIcon = max(cchMaxIcon,cchTmpIcon);
|
|
cchMaxWorkingDir = max(cchMaxWorkingDir,cchTmpWorkingDir);
|
|
cchMaxRelPath = max(cchMaxRelPath,cchTmpRelPath);
|
|
cchMaxArg = max(cchMaxArg,cchTmpArg);
|
|
}
|
|
if (cchMaxLnkFile)
|
|
{
|
|
if (!(lpszLnkFile = (LPTSTR)malloc(++cchMaxLnkFile * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxPath)
|
|
{
|
|
if (!(lpszPath = (LPTSTR)malloc(++cchMaxPath * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxIcon)
|
|
{
|
|
if (!(lpszIcon = (LPTSTR)malloc(++cchMaxIcon * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxWorkingDir)
|
|
{
|
|
if (!(lpszWorkingDir = (LPTSTR)malloc(++cchMaxWorkingDir * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxRelPath)
|
|
{
|
|
if (!(lpszRelPath = (LPTSTR)malloc(++cchMaxRelPath * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (cchMaxArg)
|
|
{
|
|
if (!(lpszArg = (LPTSTR)malloc(++cchMaxArg * sizeof(TCHAR))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
hr = CoCreateInstance (CLSID_ShellLink,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IShellLink,
|
|
(void **)&psl);
|
|
|
|
if (FAILED (hr))
|
|
{
|
|
psl = NULL;
|
|
goto Cleanup;
|
|
}
|
|
// Get a pointer to the IPersistFile interface.
|
|
hr = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
|
|
if (FAILED(hr))
|
|
{
|
|
ppf = NULL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
for(LineNo=0; LineNo<LineCount; LineNo++)
|
|
{
|
|
BOOL bSucceededOnce = FALSE;
|
|
SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext);
|
|
if (lpszLnkFile)
|
|
{
|
|
SetupGetStringField(&InfContext,1,lpszLnkFile,cchMaxLnkFile,NULL);
|
|
}
|
|
if (lpszPath)
|
|
{
|
|
SetupGetStringField(&InfContext,2,lpszPath,cchMaxPath,NULL);
|
|
}
|
|
if (lpszRelPath)
|
|
{
|
|
SetupGetStringField(&InfContext,3,lpszRelPath,cchMaxRelPath,NULL);
|
|
}
|
|
if (lpszIcon)
|
|
{
|
|
SetupGetStringField(&InfContext,4,lpszIcon,cchMaxIcon,NULL);
|
|
}
|
|
if (lpszWorkingDir)
|
|
{
|
|
SetupGetStringField(&InfContext,5,lpszWorkingDir,cchMaxWorkingDir,NULL);
|
|
}
|
|
if (lpszArg)
|
|
{
|
|
SetupGetStringField(&InfContext,6,lpszArg,cchMaxArg,NULL);
|
|
}
|
|
bFileAttribChanged = FALSE;
|
|
dwFileAttrib = GetFileAttributes(lpszLnkFile);
|
|
if (INVALID_FILE_ATTRIBUTES == dwFileAttrib)
|
|
{
|
|
//but put a waring log here
|
|
continue;
|
|
}
|
|
|
|
if ( (dwFileAttrib & FILE_ATTRIBUTE_READONLY)
|
|
||(dwFileAttrib & FILE_ATTRIBUTE_SYSTEM) )
|
|
{
|
|
if (!SetFileAttributes(lpszLnkFile,FILE_ATTRIBUTE_NORMAL))
|
|
{
|
|
//but put a waring log here
|
|
continue;
|
|
}
|
|
bFileAttribChanged = TRUE;
|
|
}
|
|
hr = ppf->Load (lpszLnkFile, STGM_READWRITE );
|
|
if (FAILED(hr))
|
|
{
|
|
//but put a waring log here
|
|
continue;
|
|
}
|
|
if (lpszPath && lpszPath[0])
|
|
{
|
|
hr = psl->SetPath (lpszPath);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bSucceededOnce = TRUE;
|
|
}
|
|
}
|
|
if (lpszRelPath && lpszRelPath[0])
|
|
{
|
|
hr = psl->SetRelativePath(lpszRelPath,0);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bSucceededOnce = TRUE;
|
|
}
|
|
}
|
|
if (lpszIcon && lpszIcon[0])
|
|
{
|
|
TCHAR szGotPath[MAX_PATH];
|
|
hr = psl->GetIconLocation (szGotPath,ARRAYSIZE(szGotPath),&nIcon);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psl->SetIconLocation (lpszIcon,nIcon);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bSucceededOnce = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (lpszWorkingDir && lpszWorkingDir[0])
|
|
{
|
|
hr = psl->SetWorkingDirectory (lpszWorkingDir);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bSucceededOnce = TRUE;
|
|
}
|
|
}
|
|
if (lpszArg && lpszArg[0])
|
|
{
|
|
hr = psl->SetArguments (lpszArg);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
bSucceededOnce = TRUE;
|
|
}
|
|
}
|
|
if (bSucceededOnce)
|
|
{
|
|
hr = ppf->Save (lpszLnkFile,TRUE);
|
|
if (! SUCCEEDED (hr))
|
|
{
|
|
DPF (dlError,TEXT("FixPathInLink: Save %s Error = %d"), lpszLnkFile,hr);
|
|
}
|
|
else
|
|
{
|
|
DPF (dlInfo,TEXT("FixPathInLink: Save %s OK = %d"), lpszLnkFile,hr);
|
|
}
|
|
}
|
|
if (bFileAttribChanged)
|
|
{
|
|
SetFileAttributes (lpszLnkFile, dwFileAttrib);
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if (psl)
|
|
{
|
|
psl->Release ();
|
|
}
|
|
if (ppf)
|
|
{
|
|
ppf->Release ();
|
|
}
|
|
FreePointer(lpszPath);
|
|
FreePointer(lpszIcon);
|
|
FreePointer(lpszRelPath);
|
|
FreePointer(lpszWorkingDir);
|
|
FreePointer(lpszArg);
|
|
FreePointer(lpszLnkFile);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT RenameRDN(
|
|
LPTSTR lpContainerPathWithLDAP,
|
|
LPTSTR lpOldFQDNWithLDAP,
|
|
LPTSTR lpNewRDNWithCN
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IADsContainer *pContainer = NULL;
|
|
IDispatch *pDispatch = NULL;
|
|
BSTR bstrOldFQDNWithLDAP = SysAllocString(lpOldFQDNWithLDAP);
|
|
BSTR bstrNewRDNWithCN = SysAllocString(lpNewRDNWithCN);
|
|
|
|
if (!bstrOldFQDNWithLDAP || !bstrNewRDNWithCN )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
hr = ADsGetObject(lpContainerPathWithLDAP,
|
|
IID_IADsContainer,
|
|
(VOID **) &pContainer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Rename the RDN here
|
|
hr = pContainer->MoveHere(bstrOldFQDNWithLDAP,
|
|
bstrNewRDNWithCN,
|
|
&pDispatch);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pDispatch->Release();
|
|
}
|
|
|
|
pContainer->Release();
|
|
}
|
|
|
|
Cleanup:
|
|
if (bstrOldFQDNWithLDAP)
|
|
{
|
|
SysFreeString(bstrOldFQDNWithLDAP);
|
|
}
|
|
if (bstrNewRDNWithCN)
|
|
{
|
|
SysFreeString(bstrNewRDNWithCN);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Pass in the interface ptr to the property value
|
|
// will return a BSTR value of the data.
|
|
// The IADsPropertyValue::get_ADsType() is called to retrieve the
|
|
// ADSTYPE valued enum
|
|
// This enum is then used to determine which IADsPropertyValue method
|
|
// to call to receive the actual data
|
|
|
|
// CALLER assumes responsibility for freeing returned BSTR
|
|
HRESULT GetIADsPropertyValueAsBSTR(BSTR * pbsRet,IADsPropertyEntry *pAdsEntry, IADsPropertyValue * pAdsPV)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
long lAdsType;
|
|
hr = pAdsPV->get_ADsType(&lAdsType);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
switch (lAdsType)
|
|
{
|
|
case ADSTYPE_INVALID :
|
|
{
|
|
*pbsRet = SysAllocString(L"<ADSTYPE_INVALID>");
|
|
}
|
|
break;
|
|
|
|
case ADSTYPE_DN_STRING :
|
|
{
|
|
hr = pAdsPV->get_DNString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_CASE_EXACT_STRING :
|
|
{
|
|
hr = pAdsPV->get_CaseExactString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_CASE_IGNORE_STRING :
|
|
{
|
|
hr = pAdsPV->get_CaseIgnoreString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_PRINTABLE_STRING :
|
|
{
|
|
hr = pAdsPV->get_PrintableString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_NUMERIC_STRING :
|
|
{
|
|
hr = pAdsPV->get_NumericString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_BOOLEAN :
|
|
{
|
|
long b;
|
|
hr = pAdsPV->get_Boolean(&b);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (b)
|
|
*pbsRet = SysAllocString(L"<TRUE>");
|
|
else
|
|
*pbsRet = SysAllocString(L"<FALSE>");
|
|
}
|
|
}
|
|
break;
|
|
case ADSTYPE_INTEGER :
|
|
{
|
|
long lInt;
|
|
hr = pAdsPV->get_Integer(&lInt);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR wOut[100];
|
|
hr = StringCchPrintf(wOut,ARRAYSIZE(wOut),L"%d",lInt);
|
|
*pbsRet = SysAllocString(wOut);
|
|
}
|
|
}
|
|
break;
|
|
case ADSTYPE_OCTET_STRING :
|
|
{
|
|
*pbsRet = SysAllocString(L"<ADSTYPE_OCTET_STRING>");
|
|
BSTR bsName= NULL;
|
|
VARIANT vOctet;
|
|
DWORD dwSLBound;
|
|
DWORD dwSUBound;
|
|
void HUGEP *pArray;
|
|
VariantInit(&vOctet);
|
|
|
|
//Get the name of the property to handle
|
|
//the properties we're interested in.
|
|
pAdsEntry->get_Name(&bsName);
|
|
hr = pAdsPV->get_OctetString(&vOctet);
|
|
|
|
//Get a pointer to the bytes in the octet string.
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SafeArrayGetLBound( V_ARRAY(&vOctet),
|
|
1,
|
|
(long FAR *) &dwSLBound );
|
|
hr = SafeArrayGetUBound( V_ARRAY(&vOctet),
|
|
1,
|
|
(long FAR *) &dwSUBound );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = SafeArrayAccessData( V_ARRAY(&vOctet),
|
|
&pArray );
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
/* Since an Octet String has a specific meaning
|
|
depending on the attribute name, handle two
|
|
common ones here
|
|
*/
|
|
if (0==wcscmp(L"objectGUID", bsName))
|
|
{
|
|
//LPOLESTR szDSGUID = new WCHAR [39];
|
|
WCHAR szDSGUID[39];
|
|
|
|
//Cast to LPGUID
|
|
LPGUID pObjectGUID = (LPGUID)pArray;
|
|
//Convert GUID to string.
|
|
::StringFromGUID2(*pObjectGUID, szDSGUID, 39);
|
|
*pbsRet = SysAllocString(szDSGUID);
|
|
|
|
}
|
|
else if (0==wcscmp(L"objectSid", bsName))
|
|
{
|
|
PSID pObjectSID = (PSID)pArray;
|
|
|
|
//Convert SID to string.
|
|
LPOLESTR szSID = NULL;
|
|
ConvertSidToStringSid(pObjectSID, &szSID);
|
|
*pbsRet = SysAllocString(szSID);
|
|
LocalFree(szSID);
|
|
}
|
|
else
|
|
{
|
|
*pbsRet = SysAllocString(L"<Value of type Octet String. No Conversion>");
|
|
|
|
}
|
|
SafeArrayUnaccessData( V_ARRAY(&vOctet) );
|
|
VariantClear(&vOctet);
|
|
}
|
|
|
|
SysFreeString(bsName);
|
|
|
|
|
|
}
|
|
break;
|
|
case ADSTYPE_LARGE_INTEGER :
|
|
{
|
|
*pbsRet = SysAllocString(L"<ADSTYPE_LARGE_INTEGER>");
|
|
}
|
|
break;
|
|
case ADSTYPE_PROV_SPECIFIC :
|
|
{
|
|
*pbsRet = SysAllocString(L"<ADSTYPE_PROV_SPECIFIC>");
|
|
}
|
|
break;
|
|
case ADSTYPE_OBJECT_CLASS :
|
|
{
|
|
hr = pAdsPV->get_CaseIgnoreString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_PATH :
|
|
{
|
|
hr = pAdsPV->get_CaseIgnoreString(pbsRet);
|
|
}
|
|
break;
|
|
case ADSTYPE_NT_SECURITY_DESCRIPTOR :
|
|
{
|
|
*pbsRet = SysAllocString(L"<ADSTYPE_NT_SECURITY_DESCRIPTOR>");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
*pbsRet = SysAllocString(L"<UNRECOGNIZED>");
|
|
break;
|
|
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT PropertyValueHelper(
|
|
LPTSTR lpObjPathWithLDAP,
|
|
LPTSTR lpPropName,
|
|
LPTSTR *lplpValue,
|
|
LPTSTR lpNewValue)
|
|
{
|
|
IADsPropertyList *pList = NULL;
|
|
IADsPropertyEntry *pEntry = NULL;
|
|
IADs *pObj = NULL;
|
|
VARIANT var,varEnrty;
|
|
long valType = ADSTYPE_PATH;
|
|
HRESULT hr;
|
|
BSTR bstrPropName = NULL;
|
|
BSTR bstrNewValue = NULL;
|
|
|
|
|
|
|
|
// bind to directory object
|
|
hr = ADsGetObject(lpObjPathWithLDAP,
|
|
IID_IADsPropertyList,
|
|
(void**)&pList);
|
|
if (S_OK != hr)
|
|
{
|
|
pList = NULL;
|
|
goto exit;
|
|
}
|
|
// initialize the property cache
|
|
hr = pList->QueryInterface(IID_IADs,(void**)&pObj);
|
|
if (S_OK != hr)
|
|
{
|
|
pObj = NULL;
|
|
goto exit;
|
|
}
|
|
pObj->GetInfo();
|
|
|
|
// get a property entry
|
|
VariantInit(&varEnrty);
|
|
bstrPropName = SysAllocString(lpPropName);
|
|
if (!bstrPropName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
hr = pList->GetPropertyItem(bstrPropName, valType, &varEnrty);
|
|
|
|
hr = V_DISPATCH(&varEnrty)->QueryInterface(IID_IADsPropertyEntry,
|
|
(void**)&pEntry);
|
|
if (S_OK != hr)
|
|
{
|
|
pEntry = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
VariantInit(&var);
|
|
|
|
hr = pEntry->get_Values(&var);
|
|
if (S_OK != hr)
|
|
{
|
|
goto exit;
|
|
}
|
|
LONG dwSLBound = 0;
|
|
LONG dwSUBound = 0;
|
|
LONG i;
|
|
|
|
hr = SafeArrayGetLBound(V_ARRAY(&var),1,(long FAR *)&dwSLBound);
|
|
if (S_OK != hr)
|
|
{
|
|
goto exit;
|
|
}
|
|
hr = SafeArrayGetUBound(V_ARRAY(&var),1,(long FAR *)&dwSUBound);
|
|
if (S_OK != hr)
|
|
{
|
|
goto exit;
|
|
}
|
|
if (dwSLBound || dwSLBound)
|
|
{
|
|
//we only interested in one enrty
|
|
goto exit;
|
|
}
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
|
|
i = 0;
|
|
hr = SafeArrayGetElement(V_ARRAY(&var),(long FAR *)&i,&v);
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
IDispatch * pDispEntry = V_DISPATCH(&v);
|
|
IADsPropertyValue * pAdsPV = NULL;
|
|
|
|
hr = pDispEntry->QueryInterface(IID_IADsPropertyValue,(void **) &pAdsPV);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bValue;
|
|
|
|
// Get the value as a BSTR
|
|
hr = GetIADsPropertyValueAsBSTR(&bValue,pEntry,pAdsPV);
|
|
if (hr == S_OK)
|
|
{
|
|
if (lplpValue)
|
|
{
|
|
*lplpValue = (LPTSTR)malloc( (lstrlen(bValue)+1)*sizeof(TCHAR));
|
|
if (!*lplpValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
hr = StringCchCopy(*lplpValue,lstrlen(bValue)+1,bValue);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (lpNewValue)
|
|
{
|
|
bstrNewValue = SysAllocString(lpNewValue);
|
|
if (!bstrNewValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
hr = pAdsPV->put_CaseIgnoreString(bstrNewValue);
|
|
}
|
|
i = 0;
|
|
hr = SafeArrayPutElement(V_ARRAY(&var),&i,&v);
|
|
if (hr != S_OK)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
hr = pEntry->put_ControlCode(ADS_PROPERTY_UPDATE);
|
|
|
|
hr = pEntry->put_Values(var);
|
|
|
|
pList->PutPropertyItem(varEnrty);
|
|
pObj->SetInfo();
|
|
hr = S_OK;
|
|
|
|
exit:;
|
|
if (bstrPropName)
|
|
{
|
|
SysFreeString(bstrPropName);
|
|
}
|
|
if (bstrNewValue)
|
|
{
|
|
SysFreeString(bstrNewValue);
|
|
}
|
|
if (pEntry)
|
|
{
|
|
pEntry->Release();
|
|
}
|
|
if (pObj)
|
|
{
|
|
pObj->Release();
|
|
}
|
|
if (pList)
|
|
{
|
|
pList->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL UpdateSecurityTemplatesSection (
|
|
LPTSTR lpINFFile,
|
|
LPTSTR lpNewInf,
|
|
LPTSTR lpszSection,
|
|
PREG_STRING_REPLACE lpStrList)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cchInSection, CchBufSize, cchOutputSize, cchBufLen;
|
|
DWORD dwAttrib;
|
|
BOOL bUpdated = FALSE;
|
|
LPTSTR lpBuf = NULL;
|
|
LPTSTR lpNewBuf, lpOldBuf, lpLineBuf, lpEnd, lpOutputBuf, lpTemp;
|
|
|
|
if (lpINFFile && lpszSection)
|
|
{
|
|
//
|
|
// allocate max size of buffer
|
|
//
|
|
CchBufSize = 0x7FFFF;
|
|
do
|
|
{
|
|
if (lpBuf)
|
|
{
|
|
MEMFREE(lpBuf);
|
|
CchBufSize *= 2;
|
|
}
|
|
lpBuf = (LPTSTR) MEMALLOC(CchBufSize * sizeof(TCHAR));
|
|
if (!lpBuf)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
cchInSection = GetPrivateProfileSection(lpszSection,
|
|
lpBuf,
|
|
CchBufSize,
|
|
lpINFFile);
|
|
} while (cchInSection == CchBufSize -2);
|
|
|
|
lpEnd = lpBuf;
|
|
lpOutputBuf = NULL;
|
|
cchOutputSize = 0;
|
|
bUpdated = FALSE;
|
|
while(lpEnd < (lpBuf + cchInSection))
|
|
{
|
|
dwAttrib = 0;
|
|
lpNewBuf = ReplaceSingleString (
|
|
lpEnd,
|
|
REG_SZ,
|
|
lpStrList,
|
|
NULL,
|
|
&dwAttrib,
|
|
TRUE);
|
|
if (!lpNewBuf)
|
|
{
|
|
lpNewBuf = ReplaceSingleString (
|
|
lpEnd,
|
|
REG_SZ,
|
|
lpStrList,
|
|
NULL,
|
|
&dwAttrib,
|
|
FALSE);
|
|
}
|
|
if (!lpNewBuf)
|
|
{
|
|
lpLineBuf = lpEnd;
|
|
}
|
|
else
|
|
{
|
|
bUpdated = TRUE;
|
|
lpLineBuf = lpNewBuf;
|
|
if (StrStrI(lpEnd, L"ProgramFiles") && StrStrI(lpNewBuf, L"Programs"))
|
|
{
|
|
//Correct the wrong string replacement
|
|
//the difference between "Programs" and "Program Files" is " File"
|
|
CchBufSize = lstrlen(lpEnd)+6;
|
|
free(lpNewBuf);
|
|
lpNewBuf = (LPTSTR)calloc(CchBufSize, sizeof(TCHAR));
|
|
if (lpNewBuf)
|
|
{
|
|
lpTemp = StrStrI(lpEnd, L"=");
|
|
if (lpTemp)
|
|
{
|
|
*lpTemp = (TCHAR)'\0';
|
|
hr = StringCchCopy(lpNewBuf, CchBufSize, lpEnd);
|
|
*lpTemp = (TCHAR)'=';
|
|
hr = StringCchCat(lpNewBuf, CchBufSize, L"= Program Files");
|
|
lpLineBuf = lpNewBuf;
|
|
if (hr != S_OK)
|
|
DPF(REGerr, L"UpdateSecurityTemplatesSection: StringCchCat failed.");
|
|
}
|
|
else
|
|
{
|
|
free(lpNewBuf);
|
|
lpLineBuf = lpEnd;
|
|
lpNewBuf = NULL;
|
|
bUpdated = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
cchBufLen = lstrlen(lpLineBuf);
|
|
|
|
lpOldBuf = NULL;
|
|
if (lpOutputBuf)
|
|
{
|
|
lpOldBuf = lpOutputBuf;
|
|
lpOutputBuf = (LPTSTR)MEMREALLOC(lpOldBuf, (cchOutputSize+cchBufLen+2)*sizeof(TCHAR));
|
|
}
|
|
else
|
|
{
|
|
lpOutputBuf = (LPTSTR)MEMALLOC((cchBufLen+2)*sizeof(TCHAR));
|
|
cchOutputSize = 0;
|
|
}
|
|
if (lpOutputBuf == NULL)
|
|
{
|
|
if (lpOldBuf)
|
|
MEMFREE(lpOldBuf);
|
|
if (lpBuf)
|
|
MEMFREE(lpBuf);
|
|
if (lpNewBuf)
|
|
free(lpNewBuf);
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCopy(&lpOutputBuf[cchOutputSize], cchBufLen+1, lpLineBuf);
|
|
if (hr != S_OK)
|
|
DPF(REGerr, L"UpdateSecurityTemplatesSection3: failed.");
|
|
|
|
cchOutputSize += cchBufLen+1;
|
|
lpEnd += lstrlen(lpEnd)+1;
|
|
if (lpNewBuf)
|
|
free(lpNewBuf);
|
|
}
|
|
if (lpOutputBuf)
|
|
lpOutputBuf[cchOutputSize] = (TCHAR)'\0';
|
|
|
|
//Workarround since the function cannot delete the section: Delete the section
|
|
WritePrivateProfileSection (lpszSection, NULL, lpNewInf);
|
|
if (!WritePrivateProfileSection (lpszSection, lpOutputBuf, lpNewInf))
|
|
{
|
|
DPF(INFerr, L"UpdateSecurityTemplatesSection: the section %s in file %s Update failed", lpszSection, lpNewInf);
|
|
}
|
|
if (lpOutputBuf)
|
|
MEMFREE(lpOutputBuf);
|
|
if (lpBuf)
|
|
MEMFREE(lpBuf);
|
|
}
|
|
Exit:
|
|
return bUpdated;
|
|
}
|
|
|
|
HRESULT UpdateSecurityTemplates(
|
|
LPTSTR lpINFFile,
|
|
PREG_STRING_REPLACE lpStrList)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DWORD cchRead;
|
|
DWORD cchBuf = 1024;
|
|
LPTSTR lpBuf, lpOldBuf;
|
|
LPTSTR lpSection;
|
|
BOOL bUpdate;
|
|
TCHAR szIndex[16];
|
|
TCHAR szNewInf[MAX_PATH];
|
|
|
|
DPF(REGmsg, L"Enter UpdateSecurityTemplates: %s", lpINFFile);
|
|
|
|
lpBuf = (LPTSTR)MEMALLOC(cchBuf * sizeof(TCHAR));
|
|
if (lpBuf == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
cchRead = GetPrivateProfileSectionNames(lpBuf,
|
|
cchBuf,
|
|
lpINFFile);
|
|
while (cchRead == (cchBuf - 2))
|
|
{
|
|
// Buffer is too small, reallocate until we have enough
|
|
lpOldBuf = lpBuf;
|
|
cchBuf += 1024;
|
|
|
|
lpBuf = (LPTSTR)MEMREALLOC(lpOldBuf, cchBuf * sizeof(TCHAR));
|
|
if (lpBuf == NULL)
|
|
{
|
|
MEMFREE(lpOldBuf);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Read the data from section again
|
|
cchRead = GetPrivateProfileSectionNames(lpBuf,
|
|
cchBuf,
|
|
lpINFFile);
|
|
}
|
|
|
|
// At this point we have big enough buffer and data in it
|
|
if (cchRead > 0)
|
|
{
|
|
hr = StringCchPrintf(szNewInf, MAX_PATH, TEXT("%s.clmt"), lpINFFile);
|
|
CopyFile(lpINFFile, szNewInf, FALSE);
|
|
lpSection = (LPTSTR)MultiSzTok(lpBuf);
|
|
bUpdate = FALSE;
|
|
while (lpSection != NULL)
|
|
{
|
|
if (UpdateSecurityTemplatesSection(lpINFFile, szNewInf, lpSection, lpStrList))
|
|
{
|
|
bUpdate = TRUE;
|
|
DPF(INFmsg, L"UpdateSecurityTemplatesSection: the section %s in file %s Updated", lpSection, lpINFFile);
|
|
}
|
|
|
|
// Get next section name
|
|
lpSection = (LPTSTR)MultiSzTok(NULL);
|
|
}
|
|
if (bUpdate)
|
|
{
|
|
g_dwKeyIndex++;
|
|
_itot(g_dwKeyIndex,szIndex,16);
|
|
if (!WritePrivateProfileString(TEXT("INF Update"),szIndex,szNewInf,g_szToDoINFFileName))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_NOT_FOUND);
|
|
}
|
|
|
|
MEMFREE(lpBuf);
|
|
DPF(REGmsg, L"Exit UpdateSecurityTemplates:");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT BatchINFUpdate(HINF hInf)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
UINT LineCount,LineNo;
|
|
DWORD dwRequired;
|
|
INFCONTEXT InfContext;
|
|
LPTSTR lpTemp;
|
|
LPTSTR lpszSection = TEXT("INF Update");
|
|
TCHAR chTemp;
|
|
TCHAR szFileNameIn[MAX_PATH];
|
|
TCHAR szFileNameOut[MAX_PATH];
|
|
|
|
DPF(INFmsg ,TEXT("Enter BatchINFUpdate:"));
|
|
if ((hInf == INVALID_HANDLE_VALUE))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
|
|
if ((LONG)LineCount <= 0)
|
|
{
|
|
hr = S_FALSE;
|
|
DPF(INFwar ,TEXT("BatchINFUpdate: failed. Section %s is empty!"),lpszSection);
|
|
goto Exit;
|
|
}
|
|
for(LineNo=0; LineNo<LineCount; LineNo++)
|
|
{
|
|
if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
|
|
{
|
|
DPF(INFerr ,TEXT("BatchINFUpdate: can not get line %n of section %s !"),LineNo, lpszSection);
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szFileNameIn,MAX_PATH,&dwRequired))
|
|
{
|
|
DPF(INFerr ,TEXT("BatchINFUpdate: get [%s] 's line %d 's Field 1 failed !"),lpszSection, LineNo);
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
lpTemp = StrStrI(szFileNameIn, TEXT(".clmt"));
|
|
if (lpTemp)
|
|
{
|
|
*lpTemp = (TCHAR)'\0';
|
|
hr = StringCchPrintf(szFileNameOut, MAX_PATH, TEXT("%s.bak"), szFileNameIn);
|
|
MoveFile(szFileNameIn, szFileNameOut);
|
|
hr = StringCchCopy(szFileNameOut, MAX_PATH, szFileNameIn);
|
|
*lpTemp = (TCHAR)'.';
|
|
MoveFile(szFileNameIn, szFileNameOut);
|
|
DPF(INFinf ,TEXT("BatchINFUpdate: %s is updated and backup file is %s.bak"), szFileNameOut, szFileNameOut);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
DPF(INFmsg ,TEXT("Exit BatchINFUpdate: hr = %d"), hr);
|
|
return hr;
|
|
}
|