/// <summary> /// Registry string value alterer which makes virtual registry rebase path string values /// to the current directory or subdirs if the file exists there. /// </summary> /// <param name="value">string value being read</param> /// <returns>altered string value</returns> internal string RebasePath(KeyIdentity key, string valueName, string value) { // Performance heuristic: return if it has no path or file name components inside the string. if (!(value.Contains("\\") || value.Contains("."))) { return(value); } // Performance heuristic: return if it is version/progid in HKCR if ((key.BaseKey == (IntPtr)Win32Api.RegPredefinedKeys.HKEY_CLASSES_ROOT || (key.BaseKey == (IntPtr)Win32Api.RegPredefinedKeys.HKEY_CURRENT_USER && key.GetRegPath().StartsWith(@"Software\Classes\", StringComparison.CurrentCultureIgnoreCase)))) { if (string.Compare(valueName, "Version", ignoreCase: true) == 0 || string.Compare(valueName, "Progid", ignoreCase: true) == 0 // InprocServer32 value is not the same as default value of InprocServer32 key // and it contains not a path but "Darwin Descriptor" used by installer || string.Compare(valueName, "InprocServer32", ignoreCase: true) == 0) { return(value); } if (string.IsNullOrEmpty(valueName) && key.GetRegPath().EndsWith(@"\Progid", StringComparison.CurrentCultureIgnoreCase)) { return(value); } } value = value.TrimEnd('\\');//some of the code below depends on a trailing \ not being there // Checking if it is a path and the path exists if (File.Exists(value) || Directory.Exists(value)) { DebugLogger.WriteLine("RebasePath skipped, path already exists: {0}", value); return(value); } string filename; try { filename = Path.GetFileName(value); } catch (Exception ex) { DebugLogger.WriteLine("RebasePath failed {0} ex: {1}", value, ex.Message); return(value); } // Checking if file pointed by path exists in the directory where .exe resides try { //TODO: this is expensive, do it once for the whole process i.e. cache list of directories and files after first retrieval ... check impact in memory usage though //TODO: this can lead to *very* hard to debug situations. //One special situation is filenames without extensions that could also map to the name of a folder in some other path //Another situation happened with 1379, a zip file contained a path c\program files\..., which can actually happen in some titles (although may have been due to auto conversion issues) //Another situation would be parts of paths that repeat in the tree, and rebasing a relative path ... we'd match the deepest one while there is no way to know the intended one string titleRoot = Utils.GetRootSearchDir(); List <string> files = new List <string>(); List <string> folders = new List <string>(); GetFilesAndFoldersFromCache(filename, folders, files); var fileList = files.ToArray(); //Directory.GetFiles(titleRoot, filename, SearchOption.AllDirectories); if (fileList.Length > 0) { string newFilePath = fileList[MaxMatch(fileList, value)]; DebugLogger.WriteLine("RebasePath {0} to: {1}", value, newFilePath); return(newFilePath); } var dirList = folders.ToArray(); //Directory.GetDirectories(titleRoot, filename, SearchOption.AllDirectories); if (dirList.Length > 0) { string newFilePath = dirList[MaxMatch(dirList, value)]; DebugLogger.WriteLine("RebasePath {0} to: {1}", value, newFilePath); return(newFilePath); } DebugLogger.WriteLine("RebasePath failed to find {0}, title root: {1}, filename: {2}", value, titleRoot, filename); } catch (Exception ex) { DebugLogger.WriteLine("RebasePath failed to find {0} ex: {1}", value, ex.ToString()); return(value); } return(value); }
private void InitCache() { GetFilesAndFolders(Utils.GetRootSearchDir(), "*", folders_, files_); }