Leaked source code of windows server 2003
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

/*++
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;
}