//++ // // Copyright (c) 1999 Microsoft Corporation // // Module Name: // CXMLParser.c // // Abstract: // This file contains the functions used by System restore in // order to real the XML encoded list of protected files. It // also performs translations between symbols like %windir% to // C:\windows // // Revision History: // Eugene Mesgar (eugenem) 6/16/99 // created // Kanwaljit Marok (kmarok ) 6/06/00 // rewritten for Whistler //-- #include #include #include #include #include #include #include #include #include #include #include #include #include "msxml.h" #include "xmlparser.h" #include "utils.h" #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile // // Local Define Section // #define MAX_BUF 1024 #define FILEID 0 // // SAFERELEASE does a safe release on COM interfaces. // Checks to see if not null, if so, calls release // method on the interface. Then sets the interface to null. // #define SAFERELEASE(p) if (p) {(p)->Release(); p = NULL;} else ; // // Default string to be assigned to environment variables if // cannot assign real folder // #define DEFAULT_UNKNOWN _TEXT("C:\\Unknown_") #define ICW_REGKEY _TEXT("App Paths\\ICWCONN1.EXE") // // Local Utility functions // void FixInconsistantBlackslash(LPTSTR pszDirectory); // // The constructor // Desc: Zero's all memory // CXMLFileListParser::CXMLFileListParser() { LONG lLoop; m_pDoc = NULL; for(lLoop = 0;lLoop < NUM_FILE_TYPES;lLoop++) { m_pDir[lLoop] = m_pExt[lLoop] = m_pFiles[lLoop] = NULL; } m_chDefaultType = _TEXT('i'); m_clComInitialized = 0; } CXMLFileListParser::~CXMLFileListParser() { LONG lLoop; for(lLoop = 0;lLoop < NUM_FILE_TYPES;lLoop++) { SAFERELEASE( m_pDir[lLoop] ); SAFERELEASE( m_pExt[lLoop] ); SAFERELEASE( m_pFiles[lLoop] ); } SAFERELEASE( m_pDoc ); // // we need to do this in a loop // so we don't leek resources with refcounting // for( lLoop = 0; lLoop < m_clComInitialized ;lLoop++) { CoUninitialize( ); // lets kill COM! } } // // Init overloaded // // Main intialization sequence // // 1) Initializes The Com Space and Creates an XML document // 2) Loads in the specified file into the XML document object // 3) Takes the document loads all the collections to populate // our sub collections ( each list gets its own heading) // 4) Sets up our Search->Replace settings // BOOL CXMLFileListParser::Init(LPCTSTR pszFile) { if(!Init()) { return FALSE; } if(!ParseFile(pszFile)) { return FALSE; } if(!LoadCollections()) { return FALSE; } if( !PopulateReplaceEntries() ) { return FALSE; } return TRUE; } BOOL CXMLFileListParser::Init() { HRESULT hr; LONG clLoop; TraceFunctEnter("Init"); // // If we are reinitializing, make sure we free up old // resources and clean up our internal variables // for( clLoop = 0; clLoop < NUM_FILE_TYPES; clLoop++) { SAFERELEASE( m_pDir[clLoop] ); SAFERELEASE( m_pExt[clLoop] ); SAFERELEASE( m_pFiles[clLoop] ); } memset(m_adwVersion,0,sizeof(DWORD) * 4); // // Initialize our COM apartment space // hr = CoInitialize(NULL); m_clComInitialized++; // // S_FALSE means the COM apartment space has been initliazed // for this procss already // if( (hr != S_OK) && (hr != S_FALSE) ) { ErrorTrace(FILEID,"CoInitialize Failed 0x%x", hr); m_clComInitialized--; goto cleanup; } // // Create an instance of our XML document object // hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDocument, (void**)&m_pDoc); if( !m_pDoc || !SUCCEEDED(hr) ) { ErrorTrace(FILEID,"CoCreateInstance Failed 0x%x", GetLastError()); goto cleanup; } TraceFunctLeave(); return(TRUE); cleanup: SAFERELEASE( m_pDoc ); TraceFunctLeave(); return(FALSE); } // // Method: LoadCollections() // // Desc: // This method goes through the XML file and finds the // , , , , // high level tags and then runs LoadOneCollection() on each of // them in order to // populate the high level m_pDir, m_pFiles, m_pExt arrays ( which // have collections for // include, exclude, sfp, etc ).. // BOOL CXMLFileListParser::LoadCollections() { IXMLElement *pRoot = NULL, *pTempElement = NULL; IXMLElementCollection *pChildren = NULL; IDispatch *pDispatch = NULL; BSTR stTagName; HRESULT hr; BSTR stTagValue; TCHAR szBuf[MAX_BUFFER]; LONG clLoop, lCollectionSize; TraceFunctEnter("CXMLFileListParser::LoadCollections"); _ASSERT(m_pDoc); if( ( hr = m_pDoc->get_root( &pRoot) ) != S_OK ) { ErrorTrace(FILEID, "IXMLDocument::GetRoot failed 0x%x",GetLastError()); goto cleanup; } if( ( hr = pRoot->get_tagName( &stTagName ) ) != S_OK ) { ErrorTrace(FILEID, "IXMLElement::get_tagName failed 0x%x", hr ); goto cleanup; } if( ConvertAndFreeBSTR( stTagName, szBuf, MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "BSTR too large for buffer", 0); goto cleanup; } // // compare filesLPCT // if( _tcsicmp( _TEXT("PCHealthProtect"), szBuf ) ) { ErrorTrace(FILEID, "Malformed XML file",0); goto cleanup; } if( ( hr = pRoot->get_children( &pChildren ) ) != S_OK ) { ErrorTrace(FILEID,"IXMLElement::get_children failed 0x%x", hr); goto cleanup; } // // we no longer need the root; // SAFERELEASE(pRoot); if( (hr = pChildren->get_length(&lCollectionSize) ) != S_OK ) { DebugTrace(FILEID,"Error Finding Length 0x%x", hr ); goto cleanup; } // // lets get references to all the sub collections // for( clLoop = 0; clLoop < lCollectionSize; clLoop++) { VARIANT v1, v2; v1.vt = VT_I4; v2.vt = VT_EMPTY; v1.lVal = clLoop; // // get a item from the collection // if( (hr = pChildren->item(v1,v2, &pDispatch) ) != S_OK ) { ErrorTrace(FILEID, "Error pChildren->item 0x%x", hr); goto cleanup; } if( ( hr = pDispatch->QueryInterface(IID_IXMLElement, (void **) &pTempElement) ) != S_OK ) { ErrorTrace(FILEID, "Error IDispatch::QueryInterface 0x%d", hr); goto cleanup; } // // lets see which collection it is // if( (hr = pTempElement->get_tagName( &stTagName ) ) != S_OK ) { DebugTrace(FILEID, "Error in get_tagName 0x%x", hr ); goto cleanup; } if( ConvertAndFreeBSTR( stTagName, szBuf, MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "BSTR too large for buffer", 0); goto cleanup; } if( !_tcsicmp( _TEXT("DIRECTORIES"), szBuf ) ) { if( !LoadOneCollection(pTempElement, m_pDir ) ) { ErrorTrace(FILEID,"Error Loading Collection",0); goto cleanup; } } else if( !_tcsicmp( _TEXT( "FILES"), szBuf ) ) { if( !LoadOneCollection(pTempElement, m_pFiles ) ) { ErrorTrace(FILEID,"Error Loading Collection",0); goto cleanup; } } else if( !_tcsicmp( _TEXT( "EXTENSIONS"), szBuf ) ) { if( !LoadOneCollection(pTempElement, m_pExt ) ) { ErrorTrace(FILEID,"Error Loading Collection",0); goto cleanup; } } else if( !_tcsicmp( _TEXT( "VERSION"), szBuf ) ) { if( ParseVersion(pTempElement) == FALSE ) { goto cleanup; } } else if( !_tcsicmp( _TEXT( "DEFTYPE"), szBuf ) ) { if( ( hr = pTempElement->get_text( &stTagValue ) ) != S_OK ) { ErrorTrace(FILEID, "Error in IXMLElement::get_text 0x%x", hr); goto cleanup; } if( ConvertAndFreeBSTR( stTagValue, szBuf, MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "Less space in BSTR to string buffer", 0); goto cleanup; } // // make sure trail, leaing spaces don't get us messed up; // TrimString(szBuf); // // empty string? // if( szBuf[0] == 0 ) { ErrorTrace(FILEID, "Empty string passed to default type.",0); goto cleanup; } m_chDefaultType = szBuf[0]; } else { ErrorTrace(FILEID, "Undefiend XML tag in file.",0); goto cleanup; } SAFERELEASE( pTempElement); SAFERELEASE( pDispatch ); } SAFERELEASE( pChildren ); TraceFunctLeave(); return TRUE; cleanup: SAFERELEASE( pTempElement ); SAFERELEASE( pDispatch ); SAFERELEASE( pRoot ); SAFERELEASE( pChildren ); TraceFunctLeave(); return FALSE; } // // Method: LoadOneCollection(IXMLElement *, IXMLElementCollection **) // // Desc: Takes a high level node (like ) and then gets all // the sub include,exclude,sfp collections and sets them up in the // pCol array (usually passed a member variable like m_pDir, m_pFiles, // etc). // BOOL CXMLFileListParser::LoadOneCollection( IXMLElement *pColHead, IXMLElementCollection **pCol ) { HRESULT hr; IXMLElementCollection *pChildren = NULL; IXMLElement *pTempElement = NULL; IDispatch *pDispatch = NULL; LONG lCollectionSize, clLoop; BSTR stTagName; TCHAR szBuf[MAX_BUFFER]; _ASSERT( pColHead ); TraceFunctEnter("CXMLFileListParser::LoadOneCollection"); // // Lets make sure we don't have a section called // if( (hr = pColHead->get_children( &pChildren )) != S_OK ) { ErrorTrace(FILEID,"Empty get_length( &lCollectionSize ) ) != S_OK ) { DebugTrace(FILEID, "Error getting collection size. 0x%x", hr ); goto cleanup; } for( clLoop = 0; clLoop < lCollectionSize; clLoop++) { // // Set up OLE style variant varaibles to loop through all the entires // VARIANT v1, v2; v1.vt = VT_I4; v2.vt = VT_EMPTY; v1.lVal = clLoop; // // get a item from the collection // if( (hr = pChildren->item(v1,v2, &pDispatch) ) != S_OK ) { ErrorTrace(FILEID, "Error pChildren->item 0x%x", hr); goto cleanup; } if( ( hr = pDispatch->QueryInterface(IID_IXMLElement, (void **) &pTempElement) ) != S_OK ) { ErrorTrace(FILEID, "Error IDispatch::QueryInterface 0x%d", hr); goto cleanup; } SAFERELEASE( pDispatch ); // // lets see which collection it is // if( (hr = pTempElement->get_tagName( &stTagName ) ) != S_OK ) { ErrorTrace(FILEID, "Error in get_tagName 0x%x", hr); goto cleanup; } if( ConvertAndFreeBSTR( stTagName, szBuf, MAX_BUFFER) > MAX_BUFFER ) { ErrorTrace(FILEID, "Not enough space to convert BString.",0); goto cleanup; } if( !_tcsicmp( _TEXT("INCLUDE"), szBuf ) ) { if( (hr = pTempElement->get_children( & pCol[INCLUDE_COLL] ) ) != S_OK ) { DebugTrace(FILEID,"Error in IXMLElement::get_children 0x%x",hr); goto cleanup; } } else if( !_tcsicmp( _TEXT( "EXCLUDE"), szBuf ) ) { if( (hr = pTempElement->get_children( & pCol[EXCLUDE_COLL] ) ) != S_OK ) { DebugTrace(FILEID,"Error in IXMLElement::get_children 0x%x",hr); goto cleanup; } } else if( !_tcsicmp( _TEXT( "SNAPSHOT"), szBuf ) ) { if( (hr = pTempElement->get_children( & pCol[SNAPSHOT_COLL] ) ) != S_OK ) { DebugTrace(FILEID,"Error in IXMLElement::get_children 0x%x",hr); goto cleanup; } } else { ErrorTrace(FILEID, "Undefiend XML tag in file.",0); goto cleanup; } SAFERELEASE( pTempElement); } SAFERELEASE( pChildren ); TraceFunctLeave(); return TRUE; cleanup: SAFERELEASE( pTempElement ); SAFERELEASE( pDispatch ); SAFERELEASE( pChildren ); TraceFunctLeave(); return FALSE; } // // Function: ParseFile(LPCTSR pszFile) // Desc: Loads a file into the member variable m_pDoc. // BOOL CXMLFileListParser::ParseFile(LPCTSTR pszFile) { BSTR pBURL=NULL; _bstr_t FileBuffer( pszFile ); HRESULT hr; TraceFunctEnter("ParseFile"); pBURL = FileBuffer.copy(); if( !pBURL ) { ErrorTrace(FILEID, "Error allocating space for a BSTR", 0); goto cleanup; } if( (hr = m_pDoc->put_URL( pBURL ) ) != S_OK ) { DebugTrace(FILEID, "Error m_pDoc->putUrl %0x%x", hr ); goto cleanup; } if( pBURL ) { SysFreeString( pBURL ); } TraceFunctLeave(); return(TRUE); cleanup: if( pBURL ) { SysFreeString( pBURL ); } TraceFunctLeave(); return(FALSE); } // // Function: ParseVersion(IXMLElement *pVerElement) // // // Desc: This funciton is called from LoadCollections() when it hits the element // containing the XML files version. It takes an IXMLElement // object and extracts the version into the m_adwVersion array // // BOOL CXMLFileListParser::ParseVersion(IXMLElement *pVerElement) { HRESULT hr; BSTR stTagValue; TCHAR szTagValue[MAX_BUFFER]; TCHAR szBuf[256]; LONG clElement; TraceFunctEnter("CXMLFileListParser::ParseVersionElement"); if( (hr = pVerElement->get_text( & stTagValue ) ) != S_OK ) { DebugTrace(FILEID, "Error in IXMLElement::get_text 0x%x", hr ); goto cleanup; } if( ConvertAndFreeBSTR( stTagValue, szTagValue, MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "Error conveting the Bstring. Not enough buffer.",0); goto cleanup; } for( clElement = 0; clElement < 4; clElement++ ) { if( GetField(szTagValue,szBuf,clElement,_TEXT('.') ) == 0 ) break; m_adwVersion[clElement] = _ttoi( szBuf ); } TraceFunctLeave(); return(TRUE); cleanup: TraceFunctLeave(); return FALSE; } // // XML Tree traversal and general accessor functions // Exposed Wrappers: GetDirectory, GetFile, GetExt // GetDirectoryCount, GetFileCount, GetExtCount // // // RETURN VALUES FOR THE GET FUNCTIONS: // lBufMax -- filename was copied OK // 0 -- serious error occoured // > lBufMax -- the number of TCHARs you really need // // // BOOL *pfDisable is for the special // "protected directory" feature in the VxD. // LONG CXMLFileListParser::GetDirectory( LONG ilElement, LPTSTR pszBuf, LONG lBufMax, TCHAR chType, BOOL *pfDisable) { LONG lReturnValue=0; LONG lType; TraceFunctEnter("CXMLFileListParser::GetDirectory"); // // get the array index of this file type // lType = TranslateType( chType ); if( !m_pDoc || !m_pDir[lType] ) { TraceFunctLeave(); return 0; } if( (lReturnValue = GetFileInfo( m_pDir[lType], ilElement, pszBuf, lBufMax, pfDisable)) != lBufMax) { goto cleanup; } if( (lReturnValue = SearchAndReplace(pszBuf, lBufMax) ) != lBufMax ) { goto cleanup; } CharUpper( pszBuf ); // // make sure there are no (lead/trail spaces/tabs) // TrimString( pszBuf ); cleanup: TraceFunctLeave(); return( lReturnValue ); } LONG CXMLFileListParser::GetDirectory( LONG ilElement, LPTSTR pszBuf, LONG lBufMax, TCHAR chType) { return( GetDirectory( ilElement, pszBuf, lBufMax, chType, NULL ) ); } LONG CXMLFileListParser::GetExt( LONG ilElement, LPTSTR pszBuf, LONG lBufMax, TCHAR chType) { LONG lReturnValue=0; LONG lType; TraceFunctEnter("CXMLFileListParser::GetExt"); lType = TranslateType( chType ); if( !m_pDoc || !m_pExt[lType] ) { TraceFunctLeave(); return 0; } if( (lReturnValue = GetFileInfo(m_pExt[lType], ilElement, pszBuf, lBufMax, NULL)) != lBufMax) { goto cleanup; } if( (lReturnValue = SearchAndReplace(pszBuf, lBufMax) ) != lBufMax ) { goto cleanup; } CharUpper( pszBuf ); // // make sure there are no (lead/trail spaces/tabs) // TrimString( pszBuf ); cleanup: TraceFunctLeave(); return( lReturnValue ); } LONG CXMLFileListParser::GetFile( LONG ilElement, LPTSTR pszBuf, LONG lBufMax, TCHAR chType) { LONG lReturnValue=0; LONG lType; TraceFunctEnter("CXMLFileListParser::GetFile"); lType = TranslateType( chType ); if( !m_pDoc || !m_pFiles[lType] ) { TraceFunctLeave(); return 0; } if( (lReturnValue = GetFileInfo(m_pFiles[lType], ilElement, pszBuf, lBufMax, NULL)) != lBufMax) { goto cleanup; } if( (lReturnValue = SearchAndReplace(pszBuf, lBufMax) ) != lBufMax ) { goto cleanup; } CharUpper( pszBuf ); // // make sure there are no (lead/trail spaces/tabs) // TrimString( pszBuf ); cleanup: TraceFunctLeave(); return( lReturnValue ); } // // GetDirectory/File/ExtCount functions. // These functions give you the number of entries in a specific collection. // For example: GetFileCount(SNAPSHOT_TYPE) will return the numbert // of entries in the FILES main heading, which are under the SNAPSHOT // subheading in the XML file. // LONG CXMLFileListParser::GetDirectoryCount( TCHAR chType) { LONG lReturnValue; TraceFunctEnter("CXMLFileListParser::GetDirectoryCount"); lReturnValue = GetCollectionSize( m_pDir[TranslateType(chType)] ); TraceFunctLeave(); return( lReturnValue ); } LONG CXMLFileListParser::GetExtCount( TCHAR chType) { LONG lReturnValue; TraceFunctEnter("CXMLFileListParser::GetExtCount"); lReturnValue = GetCollectionSize( m_pExt[TranslateType(chType)] ); TraceFunctLeave(); return( lReturnValue ); } LONG CXMLFileListParser::GetFileCount( TCHAR chType) { LONG lReturnValue; TraceFunctEnter("CXMLFileListParser::GetFileCount"); lReturnValue = GetCollectionSize( m_pFiles[TranslateType(chType)] ); TraceFunctLeave(); return( lReturnValue ); } // // Main internal functions used to get by the wrappers. // // GetCollectionSize, GetFileInfo // // LONG CXMLFileListParser::GetCollectionSize( IXMLElementCollection *pCol) { LONG lCollectionSize; HRESULT hr; TraceFunctEnter("CXMLFileListParser::GetCollectionSize"); if( pCol == NULL ) { TraceFunctLeave(); return 0; } if( (hr = pCol->get_length(&lCollectionSize) ) != S_OK ) { DebugTrace(FILEID, "Error Finding Length 0x%x", hr ); goto cleanup; } TraceFunctLeave(); return(lCollectionSize); cleanup: TraceFunctLeave(); return 0; } // // RETURN VALUES: // lBufMax -- filename was copied OK // 0 -- serious error occoured // > lBufMax -- the number in TCHAR's that you need. // LONG CXMLFileListParser::GetFileInfo( IXMLElementCollection *pCol, LONG ilElement, LPTSTR pszBuf, LONG lBufMax, BOOL *pfDisable) { HRESULT hr; LONG lLen, lCollectionSize=0, clLoop, lReturnValue=0; VARIANT v1, v2; // OLE/COM BSTR variables and helper classes BSTR stTagValue; TCHAR szValueBuffer[MAX_BUFFER]; // COM interfaces IDispatch *pDispatch = NULL; IXMLElement *pTempElement = NULL; IXMLElementCollection *pChildren = NULL; TraceFunctEnter("CXMLFileListParser::GetFileInfo"); // // Basic assumptions of the code. // _ASSERT(pCol); _ASSERT(pszBuf || !lBufMax); _ASSERT(pchType); // // Set up to make sure protection code is clean // Test to see if we have an in-range request. // if( (hr = pCol->get_length(&lCollectionSize) ) != S_OK ) { DebugTrace(FILEID, "Error Finding Length 0x%x", hr ); goto cleanup; } if( ilElement >= lCollectionSize ) { ErrorTrace(FILEID, "CXMLFileListParser::GetFileInfo (Element out of range)", 0); goto cleanup; } v1.vt = VT_I4; v1.lVal = ilElement; v2.vt = VT_EMPTY; // // get a item from the collection // if( (hr = pCol->item(v1,v2, &pDispatch) ) != S_OK ) { ErrorTrace(FILEID, "Error pChildren->item 0x%x", hr); goto cleanup; } if( ( hr = pDispatch->QueryInterface(IID_IXMLElement, (void **) &pTempElement) ) != S_OK ) { ErrorTrace(FILEID, "Error IDispatch::QueryInterface 0x%d", hr); goto cleanup; } SAFERELEASE( pDispatch ); if( (hr = pTempElement->get_text( & stTagValue ) ) != S_OK ) { DebugTrace(FILEID, "Error in IXMLElement::get_text 0x%x", hr ); goto cleanup; } if( ( lLen = ConvertAndFreeBSTR( stTagValue, szValueBuffer, MAX_BUFFER ) ) > MAX_BUFFER ) { lReturnValue = lLen + 1; goto cleanup; } _tcscpy( pszBuf, szValueBuffer ); if( pfDisable ) { _bstr_t AttrName( _TEXT("DISABLE") ); VARIANT AttrValue; *pfDisable = FALSE; // // clear the variant // VariantInit( &AttrValue ); hr = pTempElement->getAttribute( AttrName, &AttrValue ); // // who cares what the property name is // if( hr == S_OK ) { *pfDisable = TRUE; VariantClear( &AttrValue ); } } SAFERELEASE( pTempElement ); lReturnValue = lBufMax; TraceFunctLeave(); return(lReturnValue); cleanup: SAFERELEASE( pTempElement ); SAFERELEASE( pDispatch ); // what about BSTR's? TraceFunctLeave(); return(lReturnValue); } BOOL CXMLFileListParser::GetVersion( LPDWORD pdwVersion) { TraceFunctEnter("CXMLFileListParser::GetVersion"); _ASSERT( pdwVersion ); memcpy( pdwVersion, m_adwVersion, sizeof(DWORD) * 4 ); TraceFunctLeave(); return(TRUE); } TCHAR CXMLFileListParser::GetDefaultType() { return( (TCHAR) CharUpper( (LPTSTR) m_chDefaultType) ); } LONG CXMLFileListParser::SearchAndReplace( LPTSTR szBuf, LONG lMaxBuf) { TCHAR szTempBuf[MAX_BUFFER]; DWORD dwResult; LONG lReturn = 0; TraceFunctEnter("CXMLFileListParser::SearchAndReplace"); dwResult = ExpandEnvironmentStrings( szBuf, szTempBuf, lMaxBuf); if( 0 == dwResult ) { DWORD dwError; dwError = GetLastError(); ErrorTrace(FILEID, "Error in search and replace ec-%d", dwError); lReturn = 0; goto cleanup; } if( dwResult > (lMaxBuf*sizeof(TCHAR) ) ) { ErrorTrace(FILEID, "Buffer too small in Search and replace.",0); lReturn = dwResult; goto cleanup; } _tcscpy( szBuf, szTempBuf ); lReturn = lMaxBuf; cleanup: TraceFunctLeave(); return lReturn; } BOOL CXMLFileListParser::DepopulateReplaceEntries() { LONG clLoop; TraceFunctEnter("CXMLFileListParser::DepopulateReplaceEntries"); // This code shouldn't do anything anymore in the new system TraceFunctLeave(); return TRUE; } BOOL GetDSRoot( TCHAR ** pszStr ) { static WCHAR str[MAX_PATH]; *pszStr = str; *str = 0; #ifdef UNICODE _stprintf( *pszStr, _TEXT("*:\\_restore.%s"), GetMachineGuid()); #else _stprintf( *pszStr, _TEXT("*:\\_restore") ); #endif return TRUE; } BOOL GetArchiveDir( TCHAR ** pszStr ) { static TCHAR str[MAX_PATH]; #if 0 *pszStr = str; _tcscpy( *pszStr, _TEXT("c:\\_restore\\archive") ); #endif return TRUE; } BOOL GetDSTemp( TCHAR ** pszStr ) { static TCHAR str[MAX_PATH]; #if 0 *pszStr = str; _tcscpy( *pszStr, _TEXT("c:\\_restore\\temp") ); #endif return TRUE; } // // CODEWORK: REMOVE NO ERROR DETECTION HACK. // BOOL CXMLFileListParser::PopulateReplaceEntries() { TCHAR szBuf[MAX_BUFFER]; DWORD dwSize; HKEY hCurrentSettings=NULL; HKEY hICWKey = NULL; HRESULT hr=0; BOOL fChgLogOpen=FALSE; LPTSTR pszDSInfo=NULL; TCHAR szLPN[MAX_BUFFER]; DWORD cbLPN; TraceFunctEnter("CXMLFileListParser::PopulateReplaceEntries()"); // windows directory if( GetWindowsDirectory( szBuf,MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "Error getting windir",0); goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("WinDir"), szBuf ); // windows system directory if( GetSystemDirectory( szBuf,MAX_BUFFER ) > MAX_BUFFER ) { ErrorTrace(FILEID, "Error getting windir",0); goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("WinSys"), szBuf ); // Alt Startup folder if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_ALTSTARTUP ,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: AltStartUp, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("AltStartUp")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("AltStartup"), szBuf ); //App data if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_APPDATA ,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: AppData, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("AppData")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("AppData"), szBuf ); // Recycle Bin ( BITBUCKET ) if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_BITBUCKET ,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: RecycleBin, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("RecycleBin")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("RecycleBin"), szBuf ); // Common Desktop if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COMMON_DESKTOPDIRECTORY ,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: CommonDesktop, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonDesktop")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonDesktop"), szBuf ); // Common Favorite if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COMMON_FAVORITES ,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: CommonFavorites, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonFavorites")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonFavorites"), szBuf ); // Common Program groups if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COMMON_PROGRAMS,FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: CommonProgramGroups, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonProgramGroups")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonProgramGroups"), szBuf ); // Common start menu directory if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COMMON_STARTMENU, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: CommonStartMenu, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonStartMenu")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonStartMenu"), szBuf ); // Common Startup Folder if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COMMON_STARTUP, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: CommonStartUp, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonStartUp")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonStartUp"), szBuf ); // cookies folder if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_COOKIES, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: Cookies, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Cookies")); } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("Cookies"), szBuf ); // desktop directory if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_DESKTOPDIRECTORY, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: DesktopDirectory, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Desktop")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("DesktopDirectory"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_FAVORITES, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: Favorites, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Favorites")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("Favorites"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_INTERNET_CACHE, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: InternetCache, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Temporary Internet Files")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("InternetCache"), szBuf ); // network neightbors if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_NETHOOD, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: Nethood, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Nethood")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("NetHood"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_PERSONAL, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: PersonalDocuments, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("PersonalDocuments")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("PersonalDocuments"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_STARTMENU, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: StartMenu, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\Start Menu")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("StartMenu"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_TEMPLATES, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: Templates, error 0x%x", dwError); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("Templates")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("Templates"), szBuf ); // favorites if( SHGetSpecialFolderPath(NULL,szBuf, CSIDL_HISTORY, FALSE) != TRUE ) { DWORD dwError = GetLastError(); ErrorTrace(FILEID, "Error getting special folder: History, error 0x%x", dwError); GetWindowsDirectory(szBuf, MAX_BUFFER); lstrcat(szBuf, _TEXT("\\History")); //goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("History"), szBuf ); //hack if( RegOpenKey( HKEY_LOCAL_MACHINE, _TEXT("Software\\Microsoft\\Windows\\CurrentVersion"), &hCurrentSettings) != ERROR_SUCCESS) { ErrorTrace(FILEID,"Error opening registry key to retrieve program files",0); goto cleanup; } dwSize = MAX_BUFFER * sizeof(TCHAR); if( RegQueryValueEx( hCurrentSettings, _TEXT("ProgramFilesDir"), NULL, NULL, (LPBYTE) szBuf, &dwSize) != ERROR_SUCCESS ) { ErrorTrace(FILEID,"Error querying program files registry key.",0); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("ProgramFilesDir")); // goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("ProgramFiles"), szBuf ); dwSize = MAX_BUFFER * sizeof(TCHAR); if( RegQueryValueEx( hCurrentSettings, _TEXT("CommonFilesDir"), NULL, NULL, (LPBYTE) szBuf, &dwSize) != ERROR_SUCCESS ) { ErrorTrace(FILEID,"Error querying common files registry key.",0); lstrcpy(szBuf, DEFAULT_UNKNOWN); lstrcat(szBuf, _TEXT("CommonFilesDir")); // goto cleanup; } FixInconsistantBlackslash(szBuf); SetEnvironmentVariable( _TEXT("CommonFiles"), szBuf ); // get the ICW dir path from the registry if (ERROR_SUCCESS == RegOpenKeyEx(hCurrentSettings, ICW_REGKEY, 0, KEY_QUERY_VALUE, &hICWKey)) { dwSize = MAX_BUFFER * sizeof(TCHAR); if (ERROR_SUCCESS == RegQueryValueEx(hICWKey, _TEXT("Path"), NULL, NULL, (LPBYTE) szBuf, &dwSize)) { // remove the extra ; in the path if it is there dwSize = lstrlen(szBuf); if (dwSize > 0) { if (szBuf[dwSize - 1] == TCHAR(';')) { szBuf[dwSize - 1] = TCHAR('\0'); } } // convert sfn to lfn cbLPN = sizeof(szLPN)/sizeof(TCHAR); if (cbLPN <= GetLongPathName(szBuf, szLPN, cbLPN)) // error { ErrorTrace(FILEID, "Error getting LPN for %s; error=%ld", szBuf, GetLastError()); lstrcpy(szLPN, DEFAULT_UNKNOWN); lstrcat(szLPN, TEXT("ConnectionWizardDir")); } } else { lstrcpy(szLPN, DEFAULT_UNKNOWN); lstrcat(szLPN, TEXT("ConnectionWizardDir")); } } else { lstrcpy(szLPN, DEFAULT_UNKNOWN); lstrcat(szLPN, TEXT("ConnectionWizardDir")); } SetEnvironmentVariable(_TEXT("ConnectionWizard"), szLPN); DebugTrace(FILEID, "ICW Path = %s", szLPN); if (hICWKey) { RegCloseKey(hICWKey); } RegCloseKey( hCurrentSettings ); hCurrentSettings = NULL; // // System restore file stuff // if( GetDSRoot( &pszDSInfo ) == TRUE ) { SetEnvironmentVariable( _TEXT("SRDataStoreRoot"), pszDSInfo ); } else { DebugTrace(FILEID, "Error getting system restore root directory",0); } if( GetArchiveDir( &pszDSInfo ) == TRUE ) { SetEnvironmentVariable( _TEXT("SRArchiveDir"), pszDSInfo ); } else { DebugTrace(FILEID, "Error getting system restore archive directory",0); } if( GetDSTemp( &pszDSInfo ) == TRUE ) { SetEnvironmentVariable( _TEXT("SRTempDir"), pszDSInfo ); } else { DebugTrace(FILEID, "Error getting system restore temp directory",0); } // CODEWORK: Do this for real SetEnvironmentVariable( _TEXT("DocAndSettingRoot"), _TEXT("C:\\Documents And Settings") ); TraceFunctLeave(); return TRUE; cleanup: if( hCurrentSettings ) { RegCloseKey( hCurrentSettings ); } // leave it, will be taken care of in the destructor TraceFunctLeave(); return (FALSE); } // // Misc utility functions // // // We are assuming the buffer is big enough to fit the bstr. // if it is not, we still // free it but return false. // LONG CXMLFileListParser::ConvertAndFreeBSTR( BSTR bstrIn, LPTSTR szpOut, LONG lMaxBuf) { LONG lLen; TraceFunctEnter("CXMLFileListParser::ConvertAndFreeBSTR"); // // Initialize the output buffer // if (szpOut) { *szpOut = 0; } // // make a copy and put it in our object. // _ASSERT( bstrIn ); _bstr_t BSTRBuffer( bstrIn, TRUE ); lLen = BSTRBuffer.length(); // // not enough buffer space. // if( lLen > (lMaxBuf+1) ) { // copy what we can out. _tcsncpy( szpOut, BSTRBuffer.operator LPTSTR(), lMaxBuf ); szpOut[lMaxBuf] = 0; SysFreeString( bstrIn ); TraceFunctLeave(); return( lLen + 1 ); } _tcscpy( szpOut, BSTRBuffer.operator LPTSTR() ); // // remove our BSTR // SysFreeString( bstrIn ); return( lMaxBuf ); } LONG CXMLFileListParser::TranslateType(TCHAR chType) { if( ( chType == _TEXT('i') ) || ( chType == _TEXT('I') ) ) { return( INCLUDE_COLL ); } else if( ( chType == _TEXT('e') ) || ( chType == _TEXT('E') ) ) { return( EXCLUDE_COLL ); } else if( ( chType == _TEXT('s') ) || ( chType == _TEXT('S') ) ) { return( SNAPSHOT_COLL ); } return( 0 ); } void CXMLFileListParser::DebugPrintTranslations() { LONG cl; LPTSTR pszStr=NULL; LPVOID pszBlock; printf("File Name Translation Values ... \n"); pszBlock = GetEnvironmentStrings(); pszStr = (LPTSTR) pszBlock; while( pszStr && *pszStr ) { _tprintf(_TEXT("%s\n"), pszStr); pszStr += (DWORD) StringLengthBytes(pszStr)/sizeof(TCHAR); } FreeEnvironmentStrings( (LPTSTR) pszBlock ); } // // A fix to the inconsistent blackslash behavior in the // shell API. // void FixInconsistantBlackslash( LPTSTR pszDirectory) { LONG lLen; _ASSERT( pszDirectory ); lLen = _tcslen( pszDirectory ); if( lLen <= 0 ) { return; } if( pszDirectory[ lLen - 1 ] == _TEXT('\\') ) { pszDirectory[lLen - 1] = 0; } }