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.
1305 lines
47 KiB
1305 lines
47 KiB
#include "StdAfx.h"
|
|
#include "clmt.h"
|
|
|
|
HRESULT VerifyRegistryLinesWithSystemRegistry(HKEY, HINF, LPCTSTR, BOOL*);
|
|
HRESULT UpdateSystemRegistryWithRegistryLines(HKEY, HINF, LPCTSTR, LPCTSTR);
|
|
HRESULT CheckAndAddHardLinkLine(HINF, LPCTSTR, LPTSTR);
|
|
|
|
|
|
|
|
#define FOLDER(csidl, strid,ids, valuename) \
|
|
{ csidl, strid, ids, valuename}
|
|
|
|
FOLDER_INFO c_rgFolderInfo[] =
|
|
{
|
|
FOLDER( CSIDL_DESKTOPDIRECTORY,
|
|
TEXT("CSIDL_DESKTOPDIRECTORY"),
|
|
0,
|
|
TEXT("Desktop")),
|
|
|
|
// _STARTUP is a subfolder of _PROGRAMS is a subfolder of _STARTMENU -- keep that order
|
|
FOLDER( CSIDL_STARTUP,
|
|
TEXT("CSIDL_STARTUP"),
|
|
0,
|
|
TEXT("Startup")),
|
|
|
|
FOLDER( CSIDL_PROGRAMS,
|
|
TEXT("CSIDL_PROGRAMS"),
|
|
0,
|
|
TEXT("Programs")),
|
|
|
|
FOLDER( CSIDL_STARTMENU,
|
|
TEXT("CSIDL_STARTMENU"),
|
|
0,
|
|
TEXT("Start Menu")),
|
|
|
|
FOLDER( CSIDL_RECENT,
|
|
TEXT("CSIDL_RECENT"),
|
|
0,
|
|
TEXT("Recent")),
|
|
|
|
FOLDER( CSIDL_SENDTO,
|
|
TEXT("CSIDL_SENDTO"),
|
|
0,
|
|
TEXT("SendTo")),
|
|
|
|
FOLDER( CSIDL_PERSONAL,
|
|
TEXT("CSIDL_PERSONAL"),
|
|
0,
|
|
TEXT("Personal")),
|
|
|
|
FOLDER( CSIDL_FAVORITES,
|
|
TEXT("CSIDL_FAVORITES"),
|
|
0,
|
|
TEXT("Favorites")),
|
|
|
|
FOLDER( CSIDL_NETHOOD,
|
|
TEXT("CSIDL_NETHOOD"),
|
|
0,
|
|
TEXT("NetHood")),
|
|
|
|
FOLDER( CSIDL_PRINTHOOD,
|
|
TEXT("CSIDL_PRINTHOOD"),
|
|
0,
|
|
TEXT("PrintHood")),
|
|
|
|
FOLDER( CSIDL_TEMPLATES,
|
|
TEXT("CSIDL_TEMPLATES"),
|
|
0,
|
|
TEXT("Templates")),
|
|
|
|
// Common special folders
|
|
|
|
// _STARTUP is a subfolder of _PROGRAMS is a subfolder of _STARTMENU -- keep that order
|
|
|
|
FOLDER( CSIDL_COMMON_STARTUP,
|
|
TEXT("CSIDL_COMMON_STARTUP"),
|
|
0,
|
|
TEXT("Common Startup")),
|
|
|
|
FOLDER( CSIDL_COMMON_PROGRAMS,
|
|
TEXT("CSIDL_COMMON_PROGRAMS"),
|
|
0,
|
|
TEXT("Common Programs")),
|
|
|
|
FOLDER( CSIDL_COMMON_STARTMENU,
|
|
TEXT("CSIDL_COMMON_STARTMENU"),
|
|
0,
|
|
TEXT("Common Start Menu")),
|
|
|
|
FOLDER( CSIDL_COMMON_DESKTOPDIRECTORY,
|
|
TEXT("CSIDL_COMMON_DESKTOPDIRECTORY"),
|
|
0,
|
|
TEXT("Common Desktop")),
|
|
|
|
FOLDER( CSIDL_COMMON_FAVORITES,
|
|
TEXT("CSIDL_COMMON_FAVORITES"),
|
|
0,
|
|
TEXT("Common Favorites")),
|
|
|
|
FOLDER( CSIDL_COMMON_APPDATA,
|
|
TEXT("CSIDL_COMMON_APPDATA"),
|
|
0,
|
|
TEXT("Common AppData")),
|
|
|
|
FOLDER( CSIDL_COMMON_TEMPLATES,
|
|
TEXT("CSIDL_COMMON_TEMPLATES"),
|
|
0,
|
|
TEXT("Common Templates")),
|
|
|
|
FOLDER( CSIDL_COMMON_DOCUMENTS,
|
|
TEXT("CSIDL_COMMON_DOCUMENTS"),
|
|
0,
|
|
TEXT("Common Documents")),
|
|
|
|
// Application Data special folder
|
|
FOLDER( CSIDL_APPDATA,
|
|
TEXT("CSIDL_APPDATA"),
|
|
0,
|
|
TEXT("AppData")),
|
|
|
|
FOLDER( CSIDL_LOCAL_APPDATA,
|
|
TEXT("CSIDL_LOCAL_APPDATA"),
|
|
0,
|
|
TEXT("Local AppData")),
|
|
|
|
// Per-user Internet-related folders
|
|
|
|
FOLDER( CSIDL_INTERNET_CACHE,
|
|
TEXT("CSIDL_INTERNET_CACHE"),
|
|
0,
|
|
TEXT("Cache")),
|
|
|
|
FOLDER( CSIDL_COOKIES,
|
|
TEXT("CSIDL_COOKIES"),
|
|
0,
|
|
TEXT("Cookies")),
|
|
|
|
FOLDER( CSIDL_HISTORY,
|
|
TEXT("CSIDL_HISTORY"),
|
|
0,
|
|
TEXT("History")),
|
|
|
|
|
|
FOLDER( CSIDL_MYPICTURES,
|
|
TEXT("CSIDL_MYPICTURES"),
|
|
0,
|
|
TEXT("My Pictures")),
|
|
|
|
|
|
FOLDER( CSIDL_ADMINTOOLS,
|
|
TEXT("CSIDL_ADMINTOOLS"),
|
|
0,
|
|
TEXT("Administrative Tools")),
|
|
|
|
FOLDER( CSIDL_COMMON_ADMINTOOLS,
|
|
TEXT("CSIDL_COMMON_ADMINTOOLS"),
|
|
0,
|
|
TEXT("Common Administrative Tools")),
|
|
|
|
FOLDER( CSIDL_MYMUSIC,
|
|
TEXT("CSIDL_MYMUSIC"),
|
|
0,
|
|
TEXT("My Music")),
|
|
|
|
|
|
FOLDER( CSIDL_COMMON_PICTURES,
|
|
TEXT("CSIDL_COMMON_PICTURES"),
|
|
0,
|
|
TEXT("CommonPictures")),
|
|
|
|
FOLDER( CSIDL_COMMON_MUSIC,
|
|
TEXT("CSIDL_COMMON_MUSIC"),
|
|
0,
|
|
TEXT("CommonMusic")),
|
|
//Private defined ID , points to %USERPROFILE%\Local Settings
|
|
FOLDER( CSIDL_QUICKLAUNCH,
|
|
TEXT("CSIDL_QUICKLAUNCH"),
|
|
0,
|
|
TEXT("Quick Launch")),
|
|
FOLDER( CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES,
|
|
TEXT("CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES"),
|
|
0,
|
|
TEXT("Services")),
|
|
FOLDER( CSIDL_COMMON_PROGRAMFILES_ACCESSARIES,
|
|
TEXT("CSIDL_COMMON_PROGRAMFILES_ACCESSARIES"),
|
|
0,
|
|
TEXT("Accessaries")),
|
|
FOLDER( CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES,
|
|
TEXT("CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES"),
|
|
0,
|
|
TEXT("Accessaries")),
|
|
FOLDER( CSIDL_LOCAL_SETTINGS,
|
|
TEXT("CSIDL_LOCAL_SETTINGS"),
|
|
0,
|
|
TEXT("Local Settings")),
|
|
//Private defined ID , points to %ALLUSERSPROFILE%\%Start_Menu%\%Programs%\%Accessories%
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES"),
|
|
0,
|
|
TEXT("Local Settings")),
|
|
//Private defined ID , points to "%USERPROFILE%\%Start_Menu%\%Programs%\%Accessories%
|
|
FOLDER( CSIDL_ACCESSORIES,
|
|
TEXT("CSIDL_ACCESSORIES"),
|
|
0,
|
|
TEXT("Local Settings")),
|
|
|
|
FOLDER( CSIDL_PF_ACCESSORIES,
|
|
TEXT("CSIDL_PF_ACCESSORIES"),
|
|
0,
|
|
TEXT("PF_AccessoriesName")),
|
|
|
|
FOLDER( CSIDL_PROGRAM_FILES_COMMON,
|
|
TEXT("CSIDL_PROGRAM_FILES_COMMON"),
|
|
0,
|
|
TEXT("CommonFilesDir")),
|
|
|
|
FOLDER( CSIDL_PROGRAM_FILES,
|
|
TEXT("CSIDL_PROGRAM_FILES"),
|
|
0,
|
|
TEXT("ProgramFilesDir")),
|
|
|
|
FOLDER( CSIDL_PROFILES_DIRECTORY,
|
|
TEXT("CSIDL_PROFILES_DIRECTORY"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
//Private defined ID , points to "%USERPROFILE%\%Start_Menu%\%Programs%\%Accessories%
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_GAMES,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_GAMES"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_WINDOWSMEDIA,
|
|
TEXT("CSIDL_COMMON_WINDOWSMEDIA"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_COVERPAGES,
|
|
TEXT("CSIDL_COMMON_COVERPAGES"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_RECEIVED_FAX,
|
|
TEXT("CSIDL_COMMON_RECEIVED_FAX"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_SENT_FAX,
|
|
TEXT("CSIDL_COMMON_SENT_FAX"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_FAX,
|
|
TEXT("CSIDL_COMMON_FAX"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_COMMON_PICTURES,
|
|
TEXT("CSIDL_COMMON_PICTURES"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_FAVORITES_LINKS,
|
|
TEXT("CSIDL_FAVORITES_LINKS"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_FAVORITES_MEDIA,
|
|
TEXT("CSIDL_FAVORITES_MEDIA"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_ACCESSORIES_ACCESSIBILITY,
|
|
TEXT("CSIDL_ACCESSORIES_ACCESSIBILITY"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_ACCESSORIES_SYSTEM_TOOLS,
|
|
TEXT("CSIDL_ACCESSORIES_SYSTEM_TOOLS"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_ACCESSORIES_ENTERTAINMENT,
|
|
TEXT("CSIDL_ACCESSORIES_ENTERTAINMENT"),
|
|
0,
|
|
TEXT("ProfilesDirectory")),
|
|
FOLDER( CSIDL_ACCESSORIES_COMMUNICATIONS,
|
|
TEXT("CSIDL_ACCESSORIES_COMMUNICATIONS"),
|
|
0,
|
|
TEXT("ProfileDirectory")),
|
|
FOLDER( CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL,
|
|
TEXT("CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL"),
|
|
0,
|
|
TEXT("ProfileDirectory")),
|
|
FOLDER( CSIDL_UAM_VOLUME,
|
|
TEXT("CSIDL_UAM_VOLUME"),
|
|
0,
|
|
TEXT("Microsoft UAM Volume")),
|
|
FOLDER( CSIDL_COMMON_SHAREDTOOLS_STATIONERY,
|
|
TEXT("CSIDL_COMMON_SHAREDTOOLS_STATIONERY"),
|
|
0,
|
|
TEXT("Stationery")),
|
|
FOLDER( CSIDL_NETMEETING_RECEIVED_FILES,
|
|
TEXT("CSIDL_NETMEETING_RECEIVED_FILES"),
|
|
0,
|
|
TEXT("Received Files")),
|
|
FOLDER( CSIDL_COMMON_NETMEETING_RECEIVED_FILES,
|
|
TEXT("CSIDL_COMMON_NETMEETING_RECEIVED_FILES"),
|
|
0,
|
|
TEXT("Received Files")),
|
|
FOLDER( CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX,
|
|
TEXT("CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX"),
|
|
0,
|
|
TEXT("Fax")),
|
|
FOLDER( CSIDL_FAX_PERSONAL_COVER_PAGES,
|
|
TEXT("CSIDL_FAX_PERSONAL_COVER_PAGES"),
|
|
0,
|
|
TEXT("Personal Coverpages")),
|
|
FOLDER( CSIDL_FAX,
|
|
TEXT("CSIDL_FAX"),
|
|
0,
|
|
TEXT("Fax")),
|
|
FOLDER (-1, NULL, 0, NULL)
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does the shell folder renaming, notice folders may not be strictly
|
|
Shell folder, since we extended CSIDL_????? by adding out private one in .h file
|
|
|
|
Arguments:
|
|
|
|
csidl - shell ID(maybe our private one )
|
|
hKeyRoot - Registry Key
|
|
hInf - INF file handle
|
|
szUserName - user name hKeyRoot belongs to
|
|
Return Value:
|
|
|
|
S_OK if succeeds
|
|
--*/
|
|
|
|
HRESULT FixFolderPath(
|
|
INT csidl,
|
|
HKEY hKeyRoot,
|
|
HINF hInf,
|
|
LPTSTR szUserName,
|
|
BOOL bCreateHardLink)
|
|
{
|
|
const FOLDER_INFO *pfi;
|
|
HRESULT hr;
|
|
HKEY hk = NULL;
|
|
TCHAR szSection[MAX_PATH];
|
|
INFCONTEXT context ;
|
|
TCHAR szTypeReg[MAX_PATH];
|
|
TCHAR szKeyReg[MAX_PATH];
|
|
TCHAR szValueNameReg[MAX_PATH];
|
|
TCHAR szOrgValueReg[MAX_PATH];
|
|
TCHAR szNewValueReg[MAX_PATH];
|
|
DWORD dwTypeReg;
|
|
|
|
int nOriIndexFldr,nNewIndexFldr;
|
|
TCHAR szPlatformFldr[MAX_PATH];
|
|
TCHAR szTypeFldr[MAX_PATH];
|
|
TCHAR szOrgValueFldr[MAX_PATH];
|
|
TCHAR szNewValueFldr[MAX_PATH];
|
|
DWORD dwPlatformFldr;
|
|
DWORD dwTypeFldr;
|
|
DWORD dwAttrib = 0;
|
|
|
|
TCHAR szPathInReg[2*MAX_PATH];
|
|
LONG lStatus;
|
|
HKEY hKey;
|
|
LPTSTR pSubKeyPath;
|
|
DWORD dwSize;
|
|
LPTSTR pExcluseFileList = NULL;
|
|
BOOL bRegistryLineAvailable = TRUE;
|
|
TCHAR szOrgLongPath[MAX_PATH],szNewLongPath[MAX_PATH];
|
|
TCHAR szOrgShortPath[MAX_PATH],szNewShortPath[MAX_PATH];
|
|
TCHAR szOrgShortPathTemplate[MAX_PATH],szNewShortPathTemplate[MAX_PATH];
|
|
TCHAR szFullPath[MAX_PATH];
|
|
int nOrgPathTemplate,nNewPathTemplate;
|
|
PREG_STRING_REPLACE pCurrTable;
|
|
|
|
|
|
//If INF file handle is invalid, just return
|
|
if (!hInf)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//Try to search ID table ,see whether it's valid
|
|
for (pfi = c_rgFolderInfo; pfi->id != -1; pfi++)
|
|
{
|
|
if (pfi->id == csidl)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//if it's not in our pre-defined id table, return with failure
|
|
if (pfi->id == -1 )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//Get the ID section name in INF file eg. [ShellFolder.CSIDL_COOKIES]
|
|
hr = StringCchCopy(szSection,MAX_PATH,SHELL_FOLDER_PREFIX);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
hr = StringCchCat(szSection,MAX_PATH,pfi->pszIdInString);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//In folder line , the 3rd field is localized folder name
|
|
// the 4th field is english folder name
|
|
//In the case of we are running before migration and in undo mode
|
|
//the source is English string , while the new string should be localized one
|
|
|
|
nOriIndexFldr = 3;
|
|
nNewIndexFldr = 4;
|
|
|
|
nOrgPathTemplate = 1;
|
|
nNewPathTemplate = 2;
|
|
|
|
pCurrTable = &g_StrReplaceTable;
|
|
|
|
|
|
// RERKBOOS: Change here!!!
|
|
//
|
|
// Check if there is a Registry line for this CSIDL_XXX section or not
|
|
// If there is, check if we need to modify system registry following the
|
|
// Registry line or not
|
|
//
|
|
hr = VerifyRegistryLinesWithSystemRegistry(hKeyRoot,
|
|
hInf,
|
|
szSection,
|
|
&bRegistryLineAvailable);
|
|
if (hr != S_OK)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//if we arrive here , it means we need to rename that folder
|
|
//Before we change folder, we need to know the original path's shortpatt
|
|
//value
|
|
|
|
hr = StringCchCopy(szOrgLongPath,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szNewLongPath,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
|
|
|
|
if (SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_LONGPATH_TEMPLATE,&context))
|
|
{
|
|
if (!SetupGetStringField(&context,nOrgPathTemplate,szOrgLongPath,MAX_PATH,NULL)
|
|
|| !SetupGetStringField(&context,nNewPathTemplate,szNewLongPath,MAX_PATH,NULL))
|
|
{
|
|
hr = StringCchCopy(szOrgLongPath,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szNewLongPath,MAX_PATH,TEXT(""));
|
|
}
|
|
}
|
|
|
|
|
|
if (SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_SHORTPATH_TEMPLATE,&context))
|
|
{
|
|
if (!SetupGetStringField(&context,nOrgPathTemplate,szOrgShortPathTemplate,MAX_PATH,NULL)
|
|
|| !SetupGetStringField(&context,nNewPathTemplate,szNewShortPathTemplate,MAX_PATH,NULL))
|
|
{
|
|
hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szFullPath,ARRAYSIZE(szFullPath),TEXT(""));
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopy(szFullPath,ARRAYSIZE(szFullPath),szOrgShortPathTemplate);
|
|
if (!GetShortPathName(szOrgShortPathTemplate,szOrgShortPath,MAX_PATH))
|
|
{
|
|
hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
|
|
hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
|
|
}
|
|
}
|
|
}
|
|
|
|
//Get the first folder line for the section just found
|
|
if (!SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_FOLDER,&context))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dw);
|
|
DPF (dlError,TEXT("can not find folder Key in section [%s] error %n"),szSection,dw);
|
|
goto Cleanup;
|
|
}
|
|
|
|
do
|
|
{
|
|
//Folder Line has 4 basic fields
|
|
//Field 1 :Platform means whether this should be excuted
|
|
// 0 = should be run both before and after migration
|
|
// 1 = should be run only after migration
|
|
// 2 = should be run only before migration
|
|
//Field 2 :Type means whether it's a folder op or file op
|
|
// 0 = foler opration
|
|
// 1 = file opration
|
|
|
|
//Field 3/4:Original and new folder name
|
|
//String after Field 4 : This only happens when run after migration,
|
|
//it contains a list of files/folders that we need to delete in original
|
|
//folder before we move to new folder
|
|
|
|
if (!SetupGetStringField(&context,1,szPlatformFldr,MAX_PATH,NULL)
|
|
|| !SetupGetStringField(&context,2,szTypeFldr,MAX_PATH,NULL)
|
|
|| ! SetupGetStringField(&context,nOriIndexFldr,szOrgValueFldr,MAX_PATH,NULL)
|
|
|| ! SetupGetStringField(&context,nNewIndexFldr,szNewValueFldr,MAX_PATH,NULL))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dw);
|
|
DPF(dlError,TEXT("get registry info failed in [%n],line %n with %n !"),context.Section ,context.Line,dw);
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwPlatformFldr = _tstoi(szPlatformFldr);
|
|
dwTypeFldr = _tstoi(szTypeFldr);
|
|
|
|
if (!g_bBeforeMig )
|
|
{
|
|
if (dwPlatformFldr == 2)
|
|
{
|
|
continue;
|
|
}
|
|
//running after migration, we try to get exclude folder list in MultiSZ
|
|
//if it's a folder entry
|
|
if (dwTypeFldr == 0)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
bTmp = SetupGetMultiSzField(&context,5,NULL,0,&dwSize);
|
|
if ( bTmp && (dwSize > 1) )
|
|
{
|
|
LPTSTR p;
|
|
|
|
pExcluseFileList = malloc(dwSize * sizeof(TCHAR));
|
|
if (!pExcluseFileList)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetMultiSzField(&context,5,pExcluseFileList,dwSize,&dwSize))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
p = pExcluseFileList;
|
|
//loop MulitSZ string and delete each file/folder
|
|
while (*p)
|
|
{
|
|
TCHAR szTmpFile[2*MAX_PATH];
|
|
|
|
hr = StringCchCopy(szTmpFile,2*MAX_PATH,szOrgValueFldr);
|
|
ConcatenatePaths(szTmpFile,p,MAX_PATH);
|
|
DeleteFile(szTmpFile);
|
|
p += (lstrlen(p)+1);
|
|
}
|
|
free(pExcluseFileList);
|
|
pExcluseFileList = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dwPlatformFldr == 1)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
if (dwTypeFldr == 0)
|
|
{
|
|
hr = MyMoveDirectory(szOrgValueFldr,szNewValueFldr,TRUE,TRUE,bCreateHardLink,pfi->id);
|
|
if (hr != S_OK)
|
|
{
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (dlError,TEXT("can not move folder from %s to %s Error: %d (%#x)"),
|
|
szOrgValueFldr,szNewValueFldr,hr,hr);
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
if (dwTypeFldr == 1)
|
|
{
|
|
hr = MyMoveFile(szOrgValueFldr,szNewValueFldr,TRUE,FALSE);
|
|
//hr = MyMoveFile(szOrgValueFldr,szNewValueFldr,FALSE,FALSE);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF (dlError,TEXT("can not move file from %s to %s "),szOrgValueFldr,szNewValueFldr);
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
}while (SetupFindNextMatchLine(&context,SHELL_FOLDER_FOLDER,&context));
|
|
|
|
CheckAndAddHardLinkLine(hInf,szSection,szUserName);
|
|
|
|
//If we arrive here, we can update the registry now
|
|
if (bRegistryLineAvailable)
|
|
{
|
|
hr = UpdateSystemRegistryWithRegistryLines(hKeyRoot,
|
|
hInf,
|
|
szSection,
|
|
szUserName);
|
|
}
|
|
if (szOrgLongPath[0])
|
|
{
|
|
|
|
if (!AddItemToStrRepaceTable(szUserName,szOrgLongPath,szNewLongPath,szFullPath,pfi->id,pCurrTable))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
if (szOrgShortPathTemplate[0])
|
|
{
|
|
TCHAR *lpOldName,*lpNewName;
|
|
TCHAR szRoot[MAX_PATH],szOldShortPath[MAX_PATH];
|
|
TCHAR *lpOldShortName,szNewShortName[MAX_PATH];
|
|
|
|
if (GetShortPathName(szOrgShortPathTemplate,szOldShortPath,ARRAYSIZE(szOldShortPath)))
|
|
{
|
|
lpOldName = _tcsrchr(szOrgShortPathTemplate,TEXT('\\'));
|
|
lpNewName = _tcsrchr(szNewShortPathTemplate,TEXT('\\'));
|
|
lpOldShortName = _tcsrchr(szOldShortPath,TEXT('\\'));
|
|
if (lpOldName && lpNewName && lpOldShortName)
|
|
{
|
|
*lpOldName = TEXT('\0');
|
|
hr = StringCchCopy(szRoot,ARRAYSIZE(szRoot),szOrgShortPathTemplate);
|
|
*lpOldName = TEXT('\\');
|
|
hr = MyGetShortPathName(szRoot,lpOldName+1,lpNewName+1,
|
|
szNewShortName,ARRAYSIZE(szNewShortName));
|
|
|
|
if ( (S_OK == hr) && MyStrCmpI(lpOldShortName,szNewShortName))
|
|
{
|
|
if (!AddItemToStrRepaceTable(szUserName,
|
|
lpOldShortName+1,
|
|
szNewShortName,
|
|
szOldShortPath,
|
|
pfi->id|0xffff0000,
|
|
pCurrTable))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if (pExcluseFileList)
|
|
{
|
|
free(pExcluseFileList);
|
|
}
|
|
return (hr);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does the shell folder renaming, notice folders may not be strictly
|
|
Shell folder, since we extended CSIDL_????? by adding out private one in .h file
|
|
|
|
Arguments:
|
|
|
|
hInf - INF file Handle
|
|
hKey - Registry Key
|
|
szUsername - user name the hKey belongs to
|
|
Return Value:
|
|
|
|
NULL
|
|
--*/
|
|
HRESULT DoShellFolderRename(HINF hInf, HKEY hKey, LPTSTR szUsername)
|
|
{
|
|
TCHAR szSection[MAX_PATH];
|
|
UINT LineCount,LineNo;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szShellCSIDL[MAX_PATH];
|
|
const FOLDER_INFO *pfi;
|
|
PREG_STRING_REPLACE pCurrTable;
|
|
HRESULT hr;
|
|
TCHAR szHardLink[MAX_PATH];
|
|
BOOL bErrorOccured = FALSE;
|
|
|
|
|
|
#define STRING_SHELL_FOLDER_PROCESS_PERUSER TEXT("Shell.Folders.RenameList.PerUser")
|
|
#define STRING_SHELL_FOLDER_PROCESS_PERSYS TEXT("Shell.Folders.RenameList.PerSystem")
|
|
#define ID_SHELL_FOLDER_PROCESS_PERUSER 0
|
|
#define ID_SHELL_FOLDER_PROCESS_PERSYS 1
|
|
|
|
if(hInf == INVALID_HANDLE_VALUE)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hKey)
|
|
{
|
|
hr = StringCchCopy(szSection,MAX_PATH,STRING_SHELL_FOLDER_PROCESS_PERUSER);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchCopy(szSection,MAX_PATH,STRING_SHELL_FOLDER_PROCESS_PERSYS);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
LineCount = (UINT)SetupGetLineCount(hInf,szSection);
|
|
if ((LONG)LineCount < 0)
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
pCurrTable = &g_StrReplaceTable;
|
|
|
|
for(LineNo=0; LineNo<LineCount; LineNo++)
|
|
{
|
|
BOOL bCreateHardLink = FALSE;
|
|
if (!SetupGetLineByIndex(hInf,szSection,LineNo,&InfContext))
|
|
{
|
|
continue;
|
|
}
|
|
if (!SetupGetStringField(&InfContext,1,szShellCSIDL,MAX_PATH,NULL))
|
|
{
|
|
continue;
|
|
}
|
|
//Try to search ID table ,see whether it's valid
|
|
for (pfi = c_rgFolderInfo; pfi->id != -1; pfi++)
|
|
{
|
|
if (!MyStrCmpI(pfi->pszIdInString,szShellCSIDL))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (pfi->id == -1 )
|
|
{
|
|
continue;
|
|
}
|
|
if (SetupGetStringField(&InfContext,2,szHardLink,MAX_PATH,NULL))
|
|
{
|
|
bCreateHardLink = TRUE;
|
|
}
|
|
hr = FixFolderPath(pfi->id, hKey,hInf,szUsername,bCreateHardLink);
|
|
if (FAILED(hr))
|
|
{
|
|
bErrorOccured = TRUE;
|
|
}
|
|
}
|
|
if (bErrorOccured)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
Cleanup:
|
|
return hr;;
|
|
}
|
|
|
|
|
|
|
|
HRESULT VerifyRegistryLinesWithSystemRegistry(
|
|
HKEY hKeyRoot,
|
|
HINF hInf,
|
|
LPCTSTR lpSection,
|
|
BOOL *pbRegistryLineAvailable
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet;
|
|
LONG lRet;
|
|
INFCONTEXT context;
|
|
BOOL bRegistryLineAvailable;
|
|
BOOL bNeedRegReset = TRUE;
|
|
TCHAR szResetType[4];
|
|
TCHAR szRegType[4];
|
|
TCHAR szValueName[MAX_PATH];
|
|
TCHAR szNewValueName[MAX_PATH];
|
|
TCHAR szNewRegKeyName[MAX_PATH];
|
|
TCHAR szRegKey[MAX_PATH];
|
|
TCHAR szOldValue[512];
|
|
TCHAR szNewValue[512];
|
|
TCHAR szValueInReg[512];
|
|
HKEY hKey;
|
|
LPTSTR lpSubKeyPath;
|
|
LPTSTR lpEnd;
|
|
DWORD cbValueInReg;
|
|
DWORD dwResetType;
|
|
DWORD dwRegType;
|
|
DWORD dwType;
|
|
|
|
// Get the Registry Lines for the section just found
|
|
bRet = SetupFindFirstLine(hInf, lpSection, SHELL_FOLDER_REGISTRY, &context);
|
|
if (!bRet)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(dlError,
|
|
TEXT("Cannot find Registry Key in section [%s], hr = 0x%X"),
|
|
lpSection,
|
|
hr);
|
|
goto EXIT;
|
|
}
|
|
|
|
*pbRegistryLineAvailable = FALSE;
|
|
bNeedRegReset = TRUE;
|
|
while (bRet)
|
|
{
|
|
bRet = SetupGetStringField(&context, 1, szResetType, ARRAYSIZE(szResetType), NULL)
|
|
&& SetupGetStringField(&context, 2, szRegType, ARRAYSIZE(szRegType), NULL)
|
|
&& SetupGetStringField(&context, 3, szRegKey, ARRAYSIZE(szRegKey), NULL);
|
|
if (bRet)
|
|
{
|
|
// Check if there is a registry key specified in Registry line or not
|
|
if (szRegKey[0] != '\0')
|
|
{
|
|
*pbRegistryLineAvailable = TRUE;
|
|
|
|
if (!Str2KeyPath(szRegKey, &hKey, &lpSubKeyPath))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
goto EXIT;
|
|
}
|
|
|
|
if (hKeyRoot)
|
|
{
|
|
hKey = hKeyRoot;
|
|
}
|
|
|
|
dwResetType = _tcstoul(szResetType, &lpEnd, 10);
|
|
switch (dwResetType)
|
|
{
|
|
//
|
|
// Value Data reset
|
|
//
|
|
case 0:
|
|
bRet = SetupGetStringField(&context,
|
|
4,
|
|
szValueName,
|
|
ARRAYSIZE(szValueName),
|
|
NULL)
|
|
&& SetupGetStringField(&context,
|
|
5,
|
|
szOldValue,
|
|
ARRAYSIZE(szOldValue),
|
|
NULL)
|
|
&& SetupGetStringField(&context,
|
|
6,
|
|
szNewValue,
|
|
ARRAYSIZE(szNewValue),
|
|
NULL);
|
|
if (!bRet)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(dlError,
|
|
TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
|
|
context.Section,
|
|
context.Line,
|
|
hr);
|
|
goto EXIT;
|
|
}
|
|
|
|
if (MyStrCmpI(szOldValue, TEXT("")) != LSTR_EQUAL)
|
|
{
|
|
cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof(TCHAR);
|
|
lRet = RegGetValue(hKey,
|
|
lpSubKeyPath,
|
|
szValueName,
|
|
&dwType,
|
|
(LPBYTE) szValueInReg,
|
|
&cbValueInReg);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lRet);
|
|
if (lRet == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
}
|
|
goto EXIT;
|
|
}
|
|
|
|
dwRegType = _tcstoul(szRegType, &lpEnd, 10);
|
|
switch (dwRegType)
|
|
{
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
if (g_bBeforeMig)
|
|
{
|
|
//If we run before upgrade, and the string in registry is not the
|
|
//same as original one defined in INF file, that means user customized
|
|
//that shell folder, we just simple return as success with failure
|
|
if (MyStrCmpI(szValueInReg, szOldValue) != LSTR_EQUAL)
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//If we run after upgrade, and the string in registry is neither the
|
|
//same as original one defined in INF file,nor the English string , that
|
|
//means user customized that shell folder, we just simple return as
|
|
//success with failure
|
|
if (MyStrCmpI(szValueInReg, szOldValue) != LSTR_EQUAL
|
|
&& MyStrCmpI(szValueInReg, szNewValue) != LSTR_EQUAL)
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
if (g_bBeforeMig)
|
|
{
|
|
if (!MultiSzSubStr(szOldValue, szValueInReg))
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!MultiSzSubStr(szOldValue, szValueInReg)
|
|
&& !MultiSzSubStr(szNewValue, szValueInReg))
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// Value Name reset
|
|
//
|
|
case 1:
|
|
bRet = SetupGetStringField(&context,
|
|
4,
|
|
szValueName,
|
|
ARRAYSIZE(szValueName),
|
|
NULL)
|
|
&& SetupGetStringField(&context,
|
|
5,
|
|
szNewValueName,
|
|
ARRAYSIZE(szNewValueName),
|
|
NULL);
|
|
if (!bRet)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(dlError,
|
|
TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
|
|
context.Section,
|
|
context.Line,
|
|
hr);
|
|
goto EXIT;
|
|
}
|
|
|
|
cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof(TCHAR);
|
|
|
|
if (g_bBeforeMig)
|
|
{
|
|
lRet = RegGetValue(hKey,
|
|
lpSubKeyPath,
|
|
szValueName,
|
|
&dwType,
|
|
(LPBYTE) szValueInReg,
|
|
&cbValueInReg);
|
|
if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = RegGetValue(hKey,
|
|
lpSubKeyPath,
|
|
szValueName,
|
|
&dwType,
|
|
(LPBYTE) szValueInReg,
|
|
&cbValueInReg);
|
|
if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
lRet = RegGetValue(hKey,
|
|
lpSubKeyPath,
|
|
szNewValueName,
|
|
&dwType,
|
|
(LPBYTE) szValueInReg,
|
|
&cbValueInReg);
|
|
if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
bNeedRegReset = FALSE;
|
|
goto EXIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// Registry Key reset
|
|
//
|
|
case 2:
|
|
bRet = SetupGetStringField(&context,
|
|
4,
|
|
szNewRegKeyName,
|
|
ARRAYSIZE(szNewRegKeyName),
|
|
NULL);
|
|
if (!bRet)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(dlError,
|
|
TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
|
|
context.Section,
|
|
context.Line,
|
|
hr);
|
|
goto EXIT;
|
|
}
|
|
|
|
break;
|
|
|
|
// Invalid type
|
|
default:
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
DPF(dlError,
|
|
TEXT("Invalid Reset Type [%d], section [%s], line [%d]"),
|
|
dwResetType,
|
|
context.Section,
|
|
context.Line);
|
|
goto EXIT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DPF(dlError,
|
|
TEXT("Get registry info failed in section [%s], line [%d] - hr = 0x%X"),
|
|
context.Section,
|
|
context.Line,
|
|
hr);
|
|
goto EXIT;
|
|
}
|
|
|
|
bRet = SetupFindNextMatchLine(&context, SHELL_FOLDER_REGISTRY, &context);
|
|
}
|
|
|
|
EXIT:
|
|
if (!bNeedRegReset)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT UpdateSystemRegistryWithRegistryLines(
|
|
HKEY hKeyRoot,
|
|
HINF hInf,
|
|
LPCTSTR lpSection,
|
|
LPCTSTR lpUserName
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bRet;
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
TCHAR szResetType[4];
|
|
TCHAR szRegType[4];
|
|
TCHAR szRegKey[MAX_PATH];
|
|
TCHAR szOldKeyName[MAX_PATH];
|
|
TCHAR szNewKeyName[MAX_PATH];
|
|
TCHAR szValueName[MAX_PATH];
|
|
TCHAR szNewValueName[MAX_PATH];
|
|
TCHAR szOldValue[512];
|
|
TCHAR szNewValue[512];
|
|
TCHAR szValueInReg[512];
|
|
DWORD cbValueInReg;
|
|
LPTSTR lpEnd;
|
|
LPTSTR lpSubKeyPath = NULL;
|
|
DWORD dwResetType;
|
|
DWORD dwRegType;
|
|
DWORD dwType;
|
|
INFCONTEXT context;
|
|
|
|
bRet = SetupFindFirstLine(hInf, lpSection, SHELL_FOLDER_REGISTRY, &context);
|
|
while (bRet && SUCCEEDED(hr))
|
|
{
|
|
SetupGetStringField(&context, 1, szResetType, ARRAYSIZE(szResetType), NULL);
|
|
SetupGetStringField(&context, 2, szRegType, ARRAYSIZE(szRegType), NULL);
|
|
SetupGetStringField(&context, 3, szRegKey, ARRAYSIZE(szRegKey), NULL);
|
|
|
|
dwResetType = _tcstoul(szResetType, &lpEnd, 10);
|
|
dwRegType = _tcstoul(szRegType, &lpEnd, 10);
|
|
|
|
switch (dwResetType)
|
|
{
|
|
case 0:
|
|
SetupGetStringField(&context, 4, szValueName, ARRAYSIZE(szValueName), NULL);
|
|
SetupGetStringField(&context, 5, szOldValue, ARRAYSIZE(szOldValue), NULL);
|
|
SetupGetStringField(&context, 6, szNewValue, ARRAYSIZE(szNewValue), NULL);
|
|
|
|
if (dwRegType == REG_MULTI_SZ)
|
|
{
|
|
if (!Str2KeyPath(szRegKey, &hKey, &lpSubKeyPath))
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
if (hKeyRoot)
|
|
{
|
|
hKey = hKeyRoot;
|
|
}
|
|
|
|
cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof (TCHAR);
|
|
|
|
lRet = RegGetValue(hKey,
|
|
lpSubKeyPath,
|
|
szValueName,
|
|
&dwType,
|
|
(LPBYTE) szValueInReg,
|
|
&cbValueInReg);
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szNewMultiSz[MAX_PATH];
|
|
DWORD cchNewMultiSz;
|
|
LPCTSTR lpNextSz;
|
|
LPTSTR lpStart;
|
|
LPTSTR lpMultiSz;
|
|
|
|
szNewMultiSz[0] = TEXT('\0');
|
|
szNewMultiSz[1] = TEXT('\0');
|
|
cchNewMultiSz = ARRAYSIZE(szNewMultiSz);
|
|
lpMultiSz = szNewMultiSz;
|
|
|
|
lpNextSz = MultiSzTok(szValueInReg);
|
|
while (lpNextSz != NULL)
|
|
{
|
|
lpStart = StrStrI(lpNextSz, szOldValue);
|
|
if (lpStart)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
INT nStartReplace;
|
|
|
|
nStartReplace = (INT) (lpStart - lpNextSz);
|
|
lstrcpyn(szTemp,
|
|
lpNextSz,
|
|
nStartReplace + 1);
|
|
hr = StringCchCat(szTemp,
|
|
ARRAYSIZE(szTemp),
|
|
szNewValue);
|
|
if (FAILED(hr))
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
nStartReplace += lstrlen(szOldValue);
|
|
hr = StringCchCat(szTemp,
|
|
ARRAYSIZE(szTemp),
|
|
(lpNextSz + nStartReplace));
|
|
if (FAILED(hr))
|
|
{
|
|
goto EXIT;
|
|
}
|
|
|
|
AppendSzToMultiSz(szTemp,
|
|
&lpMultiSz,
|
|
&cchNewMultiSz);
|
|
}
|
|
else
|
|
{
|
|
AppendSzToMultiSz(lpNextSz,
|
|
&lpMultiSz,
|
|
&cchNewMultiSz);
|
|
}
|
|
|
|
lpNextSz = MultiSzTok(NULL);
|
|
}
|
|
|
|
hr = AddRegValueRename(szRegKey,
|
|
szValueName,
|
|
NULL,
|
|
szValueInReg,
|
|
szNewMultiSz,
|
|
dwRegType,
|
|
0,
|
|
(LPTSTR) lpUserName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = AddRegValueRename(szRegKey,
|
|
szValueName,
|
|
NULL,
|
|
szOldValue,
|
|
szNewValue,
|
|
dwRegType,
|
|
0,
|
|
(LPTSTR) lpUserName);
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
SetupGetStringField(&context, 4, szValueName, ARRAYSIZE(szValueName), NULL);
|
|
SetupGetStringField(&context, 5, szNewValueName, ARRAYSIZE(szNewValueName), NULL);
|
|
|
|
hr = AddRegValueRename(szRegKey,
|
|
szValueName,
|
|
szNewValueName,
|
|
NULL,
|
|
NULL,
|
|
dwRegType,
|
|
0,
|
|
(LPTSTR) lpUserName);
|
|
break;
|
|
|
|
case 2:
|
|
SetupGetStringField(&context, 4, szOldKeyName, ARRAYSIZE(szOldKeyName), NULL);
|
|
SetupGetStringField(&context, 5, szNewKeyName, ARRAYSIZE(szNewKeyName), NULL);
|
|
|
|
hr = AddRegKeyRename(szRegKey,
|
|
szOldKeyName,
|
|
szNewKeyName,
|
|
(LPTSTR) lpUserName);
|
|
break;
|
|
}
|
|
|
|
bRet = SetupFindNextMatchLine(&context, SHELL_FOLDER_REGISTRY, &context);
|
|
}
|
|
|
|
EXIT:
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CheckAndAddHardLinkLine(
|
|
HINF hInf,
|
|
LPCTSTR lpSection,
|
|
LPTSTR lpUser
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INFCONTEXT context;
|
|
TCHAR szType[10],szLinkValue[MAX_PATH+1],szLinkName[MAX_PATH+1];
|
|
|
|
|
|
if (!SetupFindFirstLine(hInf, lpSection, TEXT("HardLink"), &context))
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
if (!SetupGetStringField(&context,1,szType,ARRAYSIZE(szType),NULL)
|
|
|| !SetupGetStringField(&context,2,szLinkName,ARRAYSIZE(szLinkName),NULL)
|
|
|| !SetupGetStringField(&context,3,szLinkValue,ARRAYSIZE(szLinkValue),NULL))
|
|
{
|
|
DWORD dw = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dw);
|
|
DPF(dlError,TEXT("get Hardlink info failed in [%n],line %n with %n !"),context.Section ,context.Line,dw);
|
|
goto Cleanup;
|
|
}
|
|
if (!lpUser || !MyStrCmpI(lpUser,TEXT("System")) || !MyStrCmpI(lpUser,DEFAULT_USER))
|
|
{
|
|
hr = AddHardLinkEntry(szLinkName, szLinkValue, szType, lpUser, NULL, NULL);
|
|
}
|
|
Cleanup:
|
|
return hr;
|
|
}
|