Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

352 lines
9.5 KiB

#include <windows.h>
#include <stdio.h>
#include <wbemcomn.h>
#include <filecach.h>
#define A51_REPOSITORY_TEMPDIR_NAME L"A51Temp"
long FlushOldCache(LPCWSTR wszRepDir);
long GetRepositoryDirectory(LPWSTR wszRepDir);
long ConvertA51ToRoswell();
long CopyA51ToRoswell(LPCWSTR wszOldRepDir, LPCWSTR wszRepDir);
long CopyA51FromDirectoryToRoswell(LPCWSTR wszOldDir, DWORD dwOldBaseLen,
CFileCache& NewCache, LPCWSTR wszNewBase,
bool bIgnoreFiles);
class CFindCloseMe
{
HANDLE m_h;
public:
CFindCloseMe(HANDLE h) : m_h(h){}
~CFindCloseMe() {FindClose(m_h);}
};
long GetRepositoryDirectory(LPWSTR wszRepDir)
{
HKEY hKey;
long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
0, KEY_READ, &hKey);
if(lRes)
return lRes;
CFileName wszTmp;
if (wszTmp == NULL)
return ERROR_OUTOFMEMORY;
DWORD dwLen = wszTmp.Length();
lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL,
(LPBYTE)(wchar_t*)wszTmp, &dwLen);
RegCloseKey(hKey);
if(lRes)
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to get the repository "
"directory from the registry: %d\n", lRes));
return lRes;
}
if (ExpandEnvironmentStringsW(wszTmp,wszRepDir,wszTmp.Length()) == 0)
return GetLastError();
//
// Append standard postfix --- that is our root
//
wcscat(wszRepDir, L"\\FS");
return ERROR_SUCCESS;
}
long ConvertA51ToRoswell()
{
long lRes;
//
// Figure out the repository directory
//
CFileName wszRepDir;
if(wszRepDir == NULL)
return ERROR_OUTOFMEMORY;
lRes = GetRepositoryDirectory(wszRepDir);
if(lRes != ERROR_SUCCESS)
return lRes;
//
// Construct a name for the backup
//
CFileName wszOldRepDir;
if(wszRepDir == NULL)
return ERROR_OUTOFMEMORY;
wcscpy(wszOldRepDir, wszRepDir);
WCHAR* pwcLastSlash = wcsrchr(wszOldRepDir, L'\\');
if(pwcLastSlash == NULL)
return ERROR_INVALID_PARAMETER;
wcscpy(pwcLastSlash+1, A51_REPOSITORY_TEMPDIR_NAME);
//
// Remove the backup, if already there. Disregard failure --- this is not
// our real operations, we are just trying to get MoveFile to succeed
//
long lRemoveRes = A51RemoveDirectory(wszOldRepDir, false);
//
// Rename it
//
if(!MoveFileW(wszRepDir, wszOldRepDir))
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to rename the repository "
"directory \nfrom '%S' to \n'%S' even after attempting to delete "
"the destination. Deletion returned %d, rename returned %d\n",
(LPCWSTR)wszRepDir, (LPCWSTR)wszOldRepDir, lRemoveRes, lRes));
return lRes;
}
lRes = EnsureDirectory(wszRepDir);
if(lRes != ERROR_SUCCESS)
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to create repository "
"directory '%S'. Error code %d\n", (LPCWSTR)wszRepDir, lRes));
return lRes;
}
//
// Do the real work --- attempting to move everything from the old directory
// to the new one
//
try
{
lRes = CopyA51ToRoswell(wszOldRepDir, wszRepDir);
}
catch(...)
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade attempt threw an exception\n"));
lRes = ERROR_INTERNAL_ERROR;
}
//
// If a failure occurred, try to reinstate old repository
//
if(lRes != ERROR_SUCCESS)
{
long lMainRes = lRes;
ERRORTRACE((LOG_WBEMCORE, "Upgrade failed to convert the repository, "
"error code %d\n", lMainRes));
lRemoveRes = A51RemoveDirectory(wszRepDir, false);
if(!MoveFileW(wszOldRepDir, wszRepDir))
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Upgrade failed to rename the repository "
"back from '%S' to '%S' with error code %d, even after "
"attempting to delete the destination (with error code %d).\n"
"WMI is now unusable!\n", (LPCWSTR)wszOldRepDir,
(LPCWSTR)wszRepDir, lRes, lRemoveRes));
}
else
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade restored the old repository "
"back. The old version is now functional\n"));
}
return lMainRes;
}
//
// Time to delete the backup
//
lRes = A51RemoveDirectory(wszOldRepDir, false);
if(lRes != ERROR_SUCCESS)
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to remote the backup of "
"the repository in directory '%S', error code %d. This "
"will not affect operations, except inasmuch as disk space "
"is being wasted\n", (LPCWSTR)wszOldRepDir, lRes));
}
return ERROR_SUCCESS;
}
long CopyA51ToRoswell(LPCWSTR wszOldRepDir, LPCWSTR wszRepDir)
{
long lRes;
lRes = FlushOldCache(wszOldRepDir);
if(lRes != ERROR_SUCCESS)
return lRes;
//
// Instantiate the new file cache
//
CFileCache NewCache;
lRes = NewCache.Initialize(wszRepDir);
if(lRes != ERROR_SUCCESS)
return lRes;
//
// Copy all files recursively, but not the files in this directory
//
lRes = CopyA51FromDirectoryToRoswell(wszOldRepDir, wcslen(wszOldRepDir),
NewCache, wszRepDir, true);
if(lRes != ERROR_SUCCESS)
return lRes;
return ERROR_SUCCESS;
}
long CopyA51FromDirectoryToRoswell(LPCWSTR wszOldDir, DWORD dwOldBaseLen,
CFileCache& NewCache, LPCWSTR wszNewBase,
bool bIgnoreFiles)
{
long lRes;
//
// Commence enumeration of everything in this directory
//
CFileName wszMask;
if(wszMask == NULL)
return ERROR_OUTOFMEMORY;
wcscpy(wszMask, wszOldDir);
wcscat(wszMask, L"\\*");
WIN32_FIND_DATAW wfd;
HANDLE hSearch = FindFirstFileW(wszMask, &wfd);
if(hSearch == INVALID_HANDLE_VALUE)
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to enumerate files in "
"directory '%S': error code %d\n", (LPCWSTR)wszOldDir, lRes));
return lRes;
}
CFindCloseMe fcm(hSearch);
do
{
if(wfd.cFileName[0] == L'.')
continue;
//
// Construct full name
//
CFileName wszChildName;
if(wszChildName == NULL)
return ERROR_OUTOFMEMORY;
wcscpy(wszChildName, wszOldDir);
wcscat(wszChildName, L"\\");
wcscat(wszChildName, wfd.cFileName);
//
// Recurse on directories
//
if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
lRes = CopyA51FromDirectoryToRoswell(wszChildName, dwOldBaseLen,
NewCache, wszNewBase, false);
if(lRes != ERROR_SUCCESS)
return lRes;
}
else
{
//
// Check if we are skipping files
//
if(bIgnoreFiles)
continue;
//
// Read it in
//
HANDLE hFile = CreateFileW(wszChildName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Update cannot open file '%S', "
"error code %d\n", (LPCWSTR)wszChildName, lRes));
return lRes;
}
CCloseMe cm(hFile);
BY_HANDLE_FILE_INFORMATION fi;
if(!GetFileInformationByHandle(hFile, &fi))
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Update cannot open file '%S', "
"error code %d\n", (LPCWSTR)wszChildName, lRes));
return lRes;
}
DWORD dwLen = fi.nFileSizeLow;
BYTE* pBuffer = (BYTE*)TempAlloc(dwLen);
if(pBuffer == NULL)
return E_OUTOFMEMORY;
CTempFreeMe tfm(pBuffer);
DWORD dwRead;
if(!::ReadFile(hFile, pBuffer, dwLen, &dwRead, NULL))
{
lRes = GetLastError();
ERRORTRACE((LOG_WBEMCORE, "Update unable to read %d bytes "
"from file '%S' with error %d\n",
dwLen, (LPCWSTR)wszChildName, lRes));
return lRes;
}
//
// Convert the name to the new directory name
//
CFileName wszNewChildName;
if(wszNewChildName == NULL)
return ERROR_OUTOFMEMORY;
wcscpy(wszNewChildName, wszNewBase);
wcscat(wszNewChildName, wszChildName + dwOldBaseLen);
//
// Write it out
//
lRes = NewCache.WriteFile(wszNewChildName, dwLen, pBuffer);
if(lRes != ERROR_SUCCESS)
return lRes;
}
}
while(FindNextFile(hSearch, &wfd));
lRes = GetLastError();
if(lRes != ERROR_NO_MORE_FILES)
{
ERRORTRACE((LOG_WBEMCORE, "Upgrade is unable to enumerate files in "
"directory '%S': error code %d\n", (LPCWSTR)wszOldDir, lRes));
return lRes;
}
return ERROR_SUCCESS;
}