/*++ Copyright (C) 2000-2001 Microsoft Corporation Module Name: RepositoryPackager.CPP Abstract: Recursively packages the contents of the repository directory into a single file, and unpackages it. History: paulall 07-26-00 Created. a-shawnb 07-27-00 Finished. --*/ #include "precomp.h" #include #include "RepositoryPackager.h" #include // for CReleaseMe #include #include #include #include "a51tools.h" //#include wchar_t * CRepositoryPackager::backupFiles_[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"}; wchar_t * CRepositoryPackager::repDirectory_ = L"FS"; int __cdecl _adap_wbem_wcsicmp(const unsigned short * a,const unsigned short * b) { return wbem_wcsicmp(a,b); } bool CRepositoryPackager::needBackup(const wchar_t * fileName) const { const int maxSize = sizeof(backupFiles_)/sizeof(backupFiles_[0]); return (std::find_if(&backupFiles_[0], &backupFiles_[maxSize], std::not1(std::bind1st(std::ptr_fun(_adap_wbem_wcsicmp),fileName))) != backupFiles_+maxSize); }; /****************************************************************************** * * CRepositoryPackager::PackageRepository * * Description: * Iterates deeply through the repository directly and packages it up * into the given file specified by the given parameter. * Repository directory is the one retrieved from the registry. * * Parameters: * wszFilename: Filename we package everything up into * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageRepository(const wchar_t *wszFilename) { HRESULT hres = WBEM_S_NO_ERROR; CFileName wszRepositoryDirectory; HANDLE hFile = INVALID_HANDLE_VALUE; int lBackupFileNameLen = 0; bool bBackupFileExists = false; CFileName wszBackupFileName; if ((wszBackupFileName == NULL) || (wszRepositoryDirectory == NULL)) hres = WBEM_E_OUT_OF_MEMORY; //Get the root directory of the repository if (SUCCEEDED(hres)) hres = GetRepositoryDirectory(wszRepositoryDirectory); //Create a new file to package contents up to... if (SUCCEEDED(hres)) { hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { if ((GetLastError() != ERROR_FILE_EXISTS) && (GetLastError() != ERROR_ALREADY_EXISTS )) { hres = WBEM_E_INVALID_PARAMETER; } else { //We need to back up the existing file in case we fail and need to restore it StringCchCopyW(wszBackupFileName, wszBackupFileName.Length(), wszFilename); StringCchCatW(wszBackupFileName, wszBackupFileName.Length(), L"."); lBackupFileNameLen = wcslen(wszBackupFileName); for (int i = 0; i != 100; i++) { _itow(i, wszBackupFileName+lBackupFileNameLen, 10); if (MoveFileW(wszFilename, wszBackupFileName)) { //We Succeeded! bBackupFileExists = true; //Now we need to open the file again! hFile = CreateFileW(wszFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { hres = WBEM_E_INVALID_PARAMETER; } break; } } //If we failed with all them we may as well just give up here! if (!bBackupFileExists) hres = WBEM_E_INVALID_PARAMETER; } } } //Write the package header... if (SUCCEEDED(hres)) { hres = PackageHeader(hFile); } if (SUCCEEDED(hres)) { hres = PackageAllFiles(hFile, wszRepositoryDirectory); } //Write the end of package marker if (SUCCEEDED(hres)) hres = PackageTrailer(hFile); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); //If things failed we should delete the file... if (FAILED(hres)) DeleteFileW(wszFilename); //If there is a backup file, rename it back in failure case //or delete in other cases if (FAILED(hres) && bBackupFileExists && wszBackupFileName) MoveFileW(wszBackupFileName, wszFilename); else if (bBackupFileExists && wszBackupFileName) DeleteFileW(wszBackupFileName); return hres; } /****************************************************************************** * * CRepositoryPackager::UnpackageRepository * * Description: * Given the filename of a packaged up repository we unpack everything * into the repository directory specified in the registry. The * directory should have no files in it before doing this. * * Parameters: * wszFilename: Filename we unpackage everything from * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::UnpackageRepository(const wchar_t *wszFilename) { HRESULT hres = WBEM_S_NO_ERROR; wchar_t wszRepositoryDirectory[MAX_PATH+1]; HANDLE hFile = INVALID_HANDLE_VALUE; //Get the root directory of the repository hres = GetRepositoryDirectory(wszRepositoryDirectory); //open the file for unpacking... if (SUCCEEDED(hres)) { hFile = CreateFileW(wszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) hres = WBEM_E_INVALID_PARAMETER; } //unpack the package header... if (SUCCEEDED(hres)) { hres = UnPackageHeader(hFile); } //unpack the file... if (SUCCEEDED(hres)) { hres = UnPackageContentsOfDirectory(hFile, wszRepositoryDirectory); } if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); //If things failed we should delete the partially unpacked repository... if (FAILED(hres)) DeleteRepository(); return hres; } /****************************************************************************** * * CRepositoryPackager::DeleteRepository * * Description: * Delete all files and directories under the repository directory. * The repository directory location is retrieved from the registry. * * Parameters: * * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::DeleteRepository() { HRESULT hr = WBEM_S_NO_ERROR; wchar_t *wszRepositoryOrg = new wchar_t[MAX_PATH+1]; CVectorDeleteMe vdm1(wszRepositoryOrg); if (!wszRepositoryOrg) hr = WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hr)) hr = GetRepositoryDirectory(wszRepositoryOrg); //MOVE EACH OF THE FILES, ONE BY ONE for (int i = 0; SUCCEEDED(hr) && (i != 6); i++) { static wchar_t *filename[] = {L"$WinMgmt.CFG",L"INDEX.BTR",L"OBJECTS.DATA",L"Mapping1.map",L"Mapping2.map", L"Mapping.Ver"}; CFileName wszDestinationFile; if (!wszDestinationFile) hr = WBEM_E_OUT_OF_MEMORY; else { StringCchCopyW(wszDestinationFile, wszDestinationFile.Length(), wszRepositoryOrg); if (i != 0) { StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), L"\\fs"); } StringCchCatW(wszDestinationFile, wszDestinationFile.Length(), filename[i]); if (!DeleteFileW(wszDestinationFile)) { if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND)) { hr = WBEM_E_FAILED; break; } } } } return hr; } HRESULT CRepositoryPackager::PackageAllFiles(HANDLE hFile, const wchar_t *wszRepositoryDirectory) { // // internally PackageFile check for existence // this is a matter only when $WinMgMt.CFG is packeged, since it cannot be there // if PackeageFile is called from within the FindFirst/FindNext loop, then the // existence of the file is ensured by the context // HRESULT hres = PackageFile(hFile, wszRepositoryDirectory, backupFiles_[0]); if (FAILED(hres)) return hres; hres = PackageDirectory(hFile, wszRepositoryDirectory, repDirectory_); return hres; } /****************************************************************************** * * CRepositoryPackager::PackageContentsOfDirectory * * Description: * Given a directory, iterates through all files and directories and * calls into the function to package it into the file specified by the * file handle passed to the method. * * Parameters: * hFile: Handle to the destination file. * wszRepositoryDirectory: Directory to process * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory) { HRESULT hres = WBEM_S_NO_ERROR; WIN32_FIND_DATAW findFileData; HANDLE hff = INVALID_HANDLE_VALUE; //create file search pattern... CFileName wszSearchPattern; if (wszSearchPattern == NULL) hres = WBEM_E_OUT_OF_MEMORY; else { StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory); StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*"); } //Start the file iteration in this directory... if (SUCCEEDED(hres)) { hff = FindFirstFileW(wszSearchPattern, &findFileData); if (hff == INVALID_HANDLE_VALUE) { hres = WBEM_E_FAILED; } } if (SUCCEEDED(hres)) { do { //If we have a filename of '.' or '..' we ignore it... if ((wcscmp(findFileData.cFileName, L".") == 0) || (wcscmp(findFileData.cFileName, L"..") == 0)) { //Do nothing with these... } else { //This is a file, so we need to deal with that... hres = PackageFile(hFile, wszRepositoryDirectory, findFileData.cFileName); if (FAILED(hres)) break; } } while (FindNextFileW(hff, &findFileData)); } if (hff != INVALID_HANDLE_VALUE) FindClose(hff); return hres; } /****************************************************************************** * * CRepositoryPackager::GetRepositoryDirectory * * Description: * Retrieves the location of the repository directory from the registry. * * Parameters: * wszRepositoryDirectory: Array to store location in. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1]) { HKEY hKey; long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey); if(lRes) return WBEM_E_FAILED; wchar_t wszTmp[MAX_PATH + 1]; DWORD dwLen = (MAX_PATH + 1)*sizeof(wchar_t); lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen); RegCloseKey(hKey); if(lRes) return WBEM_E_FAILED; if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0) return WBEM_E_FAILED; return WBEM_S_NO_ERROR; } /****************************************************************************** * * CRepositoryPackager::PackageHeader * * Description: * Stores the header package in the given file. This is a footprint * so we can recognise if this really is one of our files when * we try to decode it. Also it allows us to version it. * * Parameters: * hFile: File handle to store header in. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageHeader(HANDLE hFile) { HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_HEADER header; StringCchCopyA(header.szSignature, 10, "FS PKG1.1"); //NOTE! MAXIMUM OF 10 CHARACTERS (INCLUDING TERMINATOR!) DWORD dwSize = 0; if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header))) hres = WBEM_E_FAILED; return hres; } /****************************************************************************** * * CRepositoryPackager::PackageDirectory * * Description: * This is the code which processes a directory. It stores the namespace * header and footer marker in the file, and also iterates through * all files and directories in that directory. * * Parameters: * hFile: File handle to store directory information in. * wszParentDirectory: Full path of parent directory * eszSubDirectory: Name of sub-directory to process * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory) { HRESULT hres = WBEM_S_NO_ERROR; { PACKAGE_SPACER_NAMESPACE header; header.dwSpacerType = PACKAGE_TYPE_NAMESPACE_START; StringCchCopyW(header.wszNamespaceName, MAX_PATH+1, wszSubDirectory); DWORD dwSize = 0; if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header))) hres = WBEM_E_FAILED; } //Get full path of new directory... CFileName wszFullDirectoryName; if (wszFullDirectoryName == NULL) hres = WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hres)) { StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\"); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory); } //Package the contents of that directory... if (SUCCEEDED(hres)) { hres = PackageContentsOfDirectory(hFile, wszFullDirectoryName); } //Now need to write the end of package marker... if (SUCCEEDED(hres)) { PACKAGE_SPACER header2; header2.dwSpacerType = PACKAGE_TYPE_NAMESPACE_END; DWORD dwSize = 0; if ((WriteFile(hFile, &header2, sizeof(header2), &dwSize, NULL) == 0) || (dwSize != sizeof(header2))) hres = WBEM_E_FAILED; } return hres; } /****************************************************************************** * * CRepositoryPackager::PackageFile * * Description: * This is the code which processes a file. It stores the file header * and the contents of the file into the destination file whose handle * is passed in. The file directory and name is passed in. * * Parameters: * hFile: File handle to store directory information in. * wszParentDirectory: Full path of parent directory * wszFilename: Name of file to process * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageFile(HANDLE hFile, const wchar_t *wszParentDirectory, wchar_t *wszFilename) { if (needBackup(wszFilename) == false) return WBEM_S_NO_ERROR; HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_SPACER_FILE header; header.dwSpacerType = PACKAGE_TYPE_FILE; StringCchCopyW(header.wszFileName, MAX_PATH+1, wszFilename); WIN32_FILE_ATTRIBUTE_DATA fileAttribs; CFileName wszFullFileName; if (wszFullFileName == NULL) hres = WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hres)) { StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory); StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\"); StringCchCatW(wszFullFileName, wszFullFileName.Length(), wszFilename); if (GetFileAttributesExW(wszFullFileName, GetFileExInfoStandard, &fileAttribs) == 0) { if (ERROR_FILE_NOT_FOUND == GetLastError()) return WBEM_S_NO_ERROR; else hres = WBEM_E_FAILED; } else { header.dwFileSize = fileAttribs.nFileSizeLow; } } //Write header... if (SUCCEEDED(hres)) { DWORD dwSize = 0; if ((WriteFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header))) hres = WBEM_E_FAILED; } //Now need to write actual contents of file to current one... but only if the file is not 0 bytes long... if (SUCCEEDED(hres) && (header.dwFileSize != 0)) { HANDLE hFromFile = CreateFileW(wszFullFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFromFile == INVALID_HANDLE_VALUE) hres = WBEM_E_FAILED; BYTE *pFileBlob = NULL; if (SUCCEEDED(hres)) { pFileBlob = new BYTE[header.dwFileSize]; if (pFileBlob == NULL) hres = WBEM_E_OUT_OF_MEMORY; } if (SUCCEEDED(hres)) { DWORD dwSize = 0; if ((ReadFile(hFromFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize)) hres = WBEM_E_FAILED; } if (SUCCEEDED(hres)) { DWORD dwSize = 0; if ((WriteFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize)) hres = WBEM_E_FAILED; } delete pFileBlob; if (hFromFile != INVALID_HANDLE_VALUE) CloseHandle(hFromFile); } return hres; } /****************************************************************************** * * CRepositoryPackager::PackageTrailer * * Description: * Writes the end of file marker to the file. * * Parameters: * hFile: File handle to store directory information in. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageTrailer(HANDLE hFile) { HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_SPACER trailer; trailer.dwSpacerType = PACKAGE_TYPE_END_OF_FILE; DWORD dwSize = 0; if ((WriteFile(hFile, &trailer, sizeof(trailer), &dwSize, NULL) == 0) || (dwSize != sizeof(trailer))) hres = WBEM_E_FAILED; return hres; } /****************************************************************************** * * CRepositoryPackager::UnPackageHeader * * Description: * Unpacks the header package in the given file. This allows us to recognise * if this really is one of our files. Also it allows us to version it. * * Parameters: * hFile: File handle to unpack header from. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::UnPackageHeader(HANDLE hFile) { HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_HEADER header; DWORD dwSize = 0; if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header))) { hres = WBEM_E_FAILED; } else if (strncmp(header.szSignature,"FS PKG1.1", 9) != 0) { hres = WBEM_E_FAILED; } return hres; } /****************************************************************************** * * CRepositoryPackager::UnPackageContentsOfDirectory * * Description: * Unpack the contents of a namespace/directory. * If a subdirectory is encountered, then it calls UnPackageDirectory to handle it. * If a file is encountered, then it calls UnPackageFile to handle it. * If no errors occur, then it will enventually encounter the end of the namespace, * which will terminate the loop and return control to the calling function. * * Parameters: * hFile: Handle to the file to unpack from * wszRepositoryDirectory: Directory to write to. * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::UnPackageContentsOfDirectory(HANDLE hFile, const wchar_t *wszRepositoryDirectory) { HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_SPACER header; DWORD dwSize; while (hres == WBEM_S_NO_ERROR) { // this loop will be exited when we either // - successfully process a complete directory/namespace // - encounter an error dwSize = 0; if ((ReadFile(hFile, &header, sizeof(header), &dwSize, NULL) == 0) || (dwSize != sizeof(header))) { hres = WBEM_E_FAILED; } else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_START) { hres = UnPackageDirectory(hFile, wszRepositoryDirectory); } else if (header.dwSpacerType == PACKAGE_TYPE_NAMESPACE_END) { // done with this directory break; } else if (header.dwSpacerType == PACKAGE_TYPE_FILE) { hres = UnPackageFile(hFile, wszRepositoryDirectory); } else if (header.dwSpacerType == PACKAGE_TYPE_END_OF_FILE) { // done unpacking break; } else { hres = WBEM_E_FAILED; } } return hres; } /****************************************************************************** * * CRepositoryPackager::UnPackageDirectory * * Description: * Unpack the start of a namespace, then call UnPackageContentsOfDirectory * to handle everything within it. * * Parameters: * hFile: File handle to unpack directory information from. * wszParentDirectory: Full path of parent directory * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::UnPackageDirectory(HANDLE hFile, const wchar_t *wszParentDirectory) { PACKAGE_SPACER_NAMESPACE header; // read namespace/directory name DWORD dwSize = 0; DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER); if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead)) { return WBEM_E_FAILED; } //Get full path of new directory... CFileName wszFullDirectoryName; if (NULL == (wchar_t *)wszFullDirectoryName) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\"); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), header.wszNamespaceName); // create directory if (!CreateDirectoryW(wszFullDirectoryName, NULL)) { if (GetLastError() != ERROR_ALREADY_EXISTS) return WBEM_E_FAILED; } // UnPackage the contents into the new directory... return UnPackageContentsOfDirectory(hFile, wszFullDirectoryName); } /****************************************************************************** * * CRepositoryPackager::UnPackageFile * * Description: * Unpack a file. * * Parameters: * hFile: File handle to unpack file information from. * wszParentDirectory: Full path of parent directory * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::UnPackageFile(HANDLE hFile, const wchar_t *wszParentDirectory) { HRESULT hres = WBEM_S_NO_ERROR; PACKAGE_SPACER_FILE header; // read file name and size DWORD dwSize = 0; DWORD dwSizeToRead = sizeof(header)-sizeof(PACKAGE_SPACER); if ((ReadFile(hFile, ((LPBYTE)&header)+sizeof(PACKAGE_SPACER), dwSizeToRead, &dwSize, NULL) == 0) || (dwSize != dwSizeToRead)) { hres = WBEM_E_FAILED; } //Get full path of new file... CFileName wszFullFileName; if (NULL == (wchar_t *)wszFullFileName) hres = WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hres)) { StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszParentDirectory); StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\"); StringCchCatW(wszFullFileName, wszFullFileName.Length(), header.wszFileName); } // create the file HANDLE hNewFile = INVALID_HANDLE_VALUE; if (SUCCEEDED(hres)) { hNewFile = CreateFileW(wszFullFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hNewFile == INVALID_HANDLE_VALUE) hres = WBEM_E_FAILED; } // read file blob and write to file if size is greater than zero if (SUCCEEDED(hres)) { if (header.dwFileSize > 0) { BYTE* pFileBlob = new BYTE[header.dwFileSize]; if (pFileBlob == NULL) hres = WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hres)) { dwSize = 0; if ((ReadFile(hFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize)) { hres = WBEM_E_FAILED; } } // write file if (SUCCEEDED(hres)) { dwSize = 0; if ((WriteFile(hNewFile, pFileBlob, header.dwFileSize, &dwSize, NULL) == 0) || (dwSize != header.dwFileSize)) hres = WBEM_E_FAILED; } if (pFileBlob) delete pFileBlob; } } if (hNewFile != INVALID_HANDLE_VALUE) CloseHandle(hNewFile); return hres; } /****************************************************************************** * * CRepositoryPackager::DeleteContentsOfDirectory * * Description: * Given a directory, iterates through all files and directories and * calls into the function to delete it. * * Parameters: * wszRepositoryDirectory: Directory to process * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::DeleteContentsOfDirectory(const wchar_t *wszRepositoryDirectory) { HRESULT hres = WBEM_S_NO_ERROR; CFileName wszFullFileName; if (wszFullFileName == NULL) return WBEM_E_OUT_OF_MEMORY; WIN32_FIND_DATAW findFileData; HANDLE hff = INVALID_HANDLE_VALUE; //create file search pattern... CFileName wszSearchPattern; if (wszSearchPattern == NULL) hres = WBEM_E_OUT_OF_MEMORY; else { StringCchCopyW(wszSearchPattern, wszSearchPattern.Length(), wszRepositoryDirectory); StringCchCatW(wszSearchPattern, wszSearchPattern.Length(), L"\\*"); } //Start the file iteration in this directory... if (SUCCEEDED(hres)) { hff = FindFirstFileW(wszSearchPattern, &findFileData); if (hff == INVALID_HANDLE_VALUE) { hres = WBEM_E_FAILED; } } if (SUCCEEDED(hres)) { do { //If we have a filename of '.' or '..' we ignore it... if ((wcscmp(findFileData.cFileName, L".") == 0) || (wcscmp(findFileData.cFileName, L"..") == 0)) { //Do nothing with these... } else if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //This is a directory, so we need to deal with that... hres = PackageDeleteDirectory(wszRepositoryDirectory, findFileData.cFileName); if (FAILED(hres)) break; } else { //This is a file, so we need to deal with that... StringCchCopyW(wszFullFileName, wszFullFileName.Length(), wszRepositoryDirectory); StringCchCatW(wszFullFileName, wszFullFileName.Length(), L"\\"); StringCchCatW(wszFullFileName, wszFullFileName.Length(), findFileData.cFileName); if (!DeleteFileW(wszFullFileName)) { hres = WBEM_E_FAILED; break; } } } while (FindNextFileW(hff, &findFileData)); } if (hff != INVALID_HANDLE_VALUE) FindClose(hff); return hres; } /****************************************************************************** * * CRepositoryPackager::PackageDeleteDirectory * * Description: * This is the code which processes a directory. It iterates through * all files and directories in that directory. * * Parameters: * wszParentDirectory: Full path of parent directory * eszSubDirectory: Name of sub-directory to process * * Return: * HRESULT: WBEM_S_NO_ERROR If successful * WBEM_E_OUT_OF_MEMORY If out of memory * WBEM_E_FAILED If anything else failed * ****************************************************************************** */ HRESULT CRepositoryPackager::PackageDeleteDirectory(const wchar_t *wszParentDirectory, wchar_t *wszSubDirectory) { HRESULT hres = WBEM_S_NO_ERROR; //Get full path of new directory... CFileName wszFullDirectoryName; if (wszFullDirectoryName == NULL) return WBEM_E_OUT_OF_MEMORY; if (SUCCEEDED(hres)) { StringCchCopyW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszParentDirectory); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), L"\\"); StringCchCatW(wszFullDirectoryName, wszFullDirectoryName.Length(), wszSubDirectory); } //Package the contents of that directory... if (SUCCEEDED(hres)) { hres = DeleteContentsOfDirectory(wszFullDirectoryName); } // now that the directory is empty, remove it if (!RemoveDirectoryW(wszFullDirectoryName)) hres = WBEM_E_FAILED; return hres; }