public TmTmProperties(TmHandle tmHandle) { InitializeComponent(); _tmHandle = tmHandle; _tmHandle.Reference(); this.UpdateInfo(); }
public static void ShowHandleProperties(SystemHandleEntry handleInfo) { try { IntPtr handle = new IntPtr(handleInfo.Handle); ProcessHandle phandle = new ProcessHandle(handleInfo.ProcessId, ProcessAccess.DupHandle); GenericHandle dupHandle = null; // Try to get a handle, since we need one for security editing. try { dupHandle = new GenericHandle(phandle, handle, 0); } catch { } PropSheetHeader64 header = new PropSheetHeader64 { dwSize = (uint)PropSheetHeader64.SizeOf, nPages = 2, dwFlags = (uint)PropSheetFlags.PSH_DEFAULT, pszCaption = "Handle Properties" }; using (HandleDetails hw = new HandleDetails()) { hw.ObjectHandle = handleInfo; hw.HandlePropertiesCallback += (control, name, typeName) => { switch (typeName.ToLowerInvariant()) { // Objects with separate property windows: case "file": case "job": case "key": case "token": case "process": { Button b = new Button { FlatStyle = FlatStyle.System, Text = "Properties" }; b.Click += (sender, e) => { try { switch (typeName.ToLowerInvariant()) { case "file": { FileUtils.ShowProperties(name); } break; case "job": { dupHandle = new GenericHandle(phandle, handle, (int)JobObjectAccess.Query); (new JobWindow(JobObjectHandle.FromHandle(dupHandle))).ShowDialog(); } break; case "key": { try { PhUtils.OpenKeyInRegedit(PhUtils.GetForegroundWindow(), name); } catch (Exception ex) { PhUtils.ShowException("Unable to open the Registry Editor", ex); } } break; case "token": { using (TokenWindow twindow = new TokenWindow(new RemoteTokenHandle(phandle, handle))) { twindow.ShowDialog(); } } break; case "process": { dupHandle = new GenericHandle(phandle, handle, (int)OSVersion.MinProcessQueryInfoAccess); int pid = ProcessHandle.FromHandle(dupHandle).ProcessId; Program.GetProcessWindow(Program.ProcessProvider.Dictionary[pid], Program.FocusWindow); } break; } } catch (Exception ex) { PhUtils.ShowException("Unable to show object properties", ex); } }; control.Controls.Add(b); } break; case "event": { dupHandle = new GenericHandle(phandle, handle, (int)EventAccess.QueryState); var eventProps = new EventProperties(EventHandle.FromHandle(dupHandle)); control.Controls.Add(eventProps); } break; case "eventpair": { dupHandle = new GenericHandle(phandle, handle, (int)EventPairAccess.All); var eventPairProps = new EventPairProperties(EventPairHandle.FromHandle(dupHandle)); control.Controls.Add(eventPairProps); } break; case "mutant": { dupHandle = new GenericHandle(phandle, handle, (int)MutantAccess.QueryState); var mutantProps = new MutantProperties(MutantHandle.FromHandle(dupHandle)); control.Controls.Add(mutantProps); } break; case "section": { dupHandle = new GenericHandle(phandle, handle, (int)SectionAccess.Query); var sectionProps = new SectionProperties(SectionHandle.FromHandle(dupHandle)); control.Controls.Add(sectionProps); } break; case "semaphore": { dupHandle = new GenericHandle(phandle, handle, (int)SemaphoreAccess.QueryState); var semaphoreProps = new SemaphoreProperties(SemaphoreHandle.FromHandle(dupHandle)); control.Controls.Add(semaphoreProps); } break; case "timer": { dupHandle = new GenericHandle(phandle, handle, (int)TimerAccess.QueryState); var timerProps = new TimerProperties(TimerHandle.FromHandle(dupHandle)); control.Controls.Add(timerProps); } break; case "tmrm": { dupHandle = new GenericHandle(phandle, handle, (int)ResourceManagerAccess.QueryInformation); var tmRmProps = new TmRmProperties(ResourceManagerHandle.FromHandle(dupHandle)); control.Controls.Add(tmRmProps); } break; case "tmtm": { dupHandle = new GenericHandle(phandle, handle, (int)TmAccess.QueryInformation); var tmTmProps = new TmTmProperties(TmHandle.FromHandle(dupHandle)); control.Controls.Add(tmTmProps); } break; } }; hw.Init(); IntPtr[] pages = new IntPtr[2]; pages[0] = hw.CreatePageHandle(); pages[1] = CreateSecurityPage(SecurityEditor.EditSecurity2( null, SecurityEditor.GetSecurableWrapper(dupHandle), hw._name, NativeTypeFactory.GetAccessEntries(NativeTypeFactory.GetObjectType(hw._typeName)) )); GCHandle gch = GCHandle.Alloc(pages, GCHandleType.Pinned); header.phpage = gch.AddrOfPinnedObject(); PropertySheetW(ref header); if (dupHandle != null) { dupHandle.Dispose(); } } } catch (Exception ex) { PhUtils.ShowException("Unable to show handle properties", ex); } }
public static void ShowHandleProperties(SystemHandleEntry handleInfo) { try { HandlePropertiesWindow window = new HandlePropertiesWindow(handleInfo); IntPtr handle = new IntPtr(handleInfo.Handle); ProcessHandle phandle = new ProcessHandle(handleInfo.ProcessId, ProcessAccess.DupHandle); GenericHandle dupHandle = null; window.HandlePropertiesCallback += (control, name, typeName) => { switch (typeName.ToLowerInvariant()) { // Objects with separate property windows: case "file": case "job": case "key": case "token": case "process": { Button b = new Button(); b.FlatStyle = FlatStyle.System; b.Text = "Properties"; b.Click += (sender, e) => { try { switch (typeName.ToLowerInvariant()) { case "file": { FileUtils.ShowProperties(name); } break; case "job": { dupHandle = new GenericHandle( phandle, handle, (int)JobObjectAccess.Query); (new JobWindow(JobObjectHandle.FromHandle(dupHandle))).ShowDialog(); } break; case "key": { try { PhUtils.OpenKeyInRegedit(PhUtils.GetForegroundWindow(), name); } catch (Exception ex) { PhUtils.ShowException("Unable to open the Registry Editor", ex); } } break; case "token": { (new TokenWindow(new RemoteTokenHandle(phandle, handle))).ShowDialog(); } break; case "process": { int pid; if (KProcessHacker.Instance != null) { pid = KProcessHacker.Instance.KphGetProcessId(phandle, handle); } else { dupHandle = new GenericHandle( phandle, handle, (int)OSVersion.MinProcessQueryInfoAccess); pid = ProcessHandle.FromHandle(dupHandle).GetProcessId(); } Program.GetProcessWindow(Program.ProcessProvider.Dictionary[pid], (f) => Program.FocusWindow(f)); } break; } } catch (Exception ex) { PhUtils.ShowException("Unable to show object properties", ex); } }; control.Controls.Add(b); } break; case "event": { dupHandle = new GenericHandle(phandle, handle, (int)EventAccess.QueryState); var eventProps = new EventProperties(EventHandle.FromHandle(dupHandle)); control.Controls.Add(eventProps); } break; case "eventpair": { dupHandle = new GenericHandle(phandle, handle, (int)EventPairAccess.All); var eventPairProps = new EventPairProperties(EventPairHandle.FromHandle(dupHandle)); control.Controls.Add(eventPairProps); } break; case "mutant": { dupHandle = new GenericHandle(phandle, handle, (int)MutantAccess.QueryState); var mutantProps = new MutantProperties(MutantHandle.FromHandle(dupHandle)); control.Controls.Add(mutantProps); } break; case "section": { dupHandle = new GenericHandle(phandle, handle, (int)SectionAccess.Query); var sectionProps = new SectionProperties(SectionHandle.FromHandle(dupHandle)); control.Controls.Add(sectionProps); } break; case "semaphore": { dupHandle = new GenericHandle(phandle, handle, (int)SemaphoreAccess.QueryState); var semaphoreProps = new SemaphoreProperties(SemaphoreHandle.FromHandle(dupHandle)); control.Controls.Add(semaphoreProps); } break; case "timer": { dupHandle = new GenericHandle(phandle, handle, (int)TimerAccess.QueryState); var timerProps = new TimerProperties(TimerHandle.FromHandle(dupHandle)); control.Controls.Add(timerProps); } break; case "tmrm": { dupHandle = new GenericHandle(phandle, handle, (int)ResourceManagerAccess.QueryInformation); var tmRmProps = new TmRmProperties(ResourceManagerHandle.FromHandle(dupHandle)); control.Controls.Add(tmRmProps); } break; case "tmtm": { dupHandle = new GenericHandle(phandle, handle, (int)TmAccess.QueryInformation); var tmTmProps = new TmTmProperties(TmHandle.FromHandle(dupHandle)); control.Controls.Add(tmTmProps); } break; } }; if (dupHandle == null) { // Try to get a handle, since we need one for security editing. try { dupHandle = new GenericHandle(phandle, handle, 0); } catch { } } window.ObjectHandle = dupHandle; window.ShowDialog(); if (dupHandle != null) { dupHandle.Dispose(); } } catch (Exception ex) { PhUtils.ShowException("Unable to show handle properties", ex); } }
public static ObjectInformation GetHandleInfo(this SystemHandleEntry thisHandle, ProcessHandle process, bool getName) { IntPtr handle = new IntPtr(thisHandle.Handle); IntPtr objectHandleI; int retLength; GenericHandle objectHandle = null; if (thisHandle.Handle == 0 || thisHandle.Handle == -1 || thisHandle.Handle == -2) { throw new WindowsException(NtStatus.InvalidHandle); } // Duplicate the handle if we're not using KPH //if (KProcessHacker.Instance == null) { Win32.NtDuplicateObject( process, handle, ProcessHandle.Current, out objectHandleI, 0, 0, 0 ).ThrowIf(); objectHandle = new GenericHandle(objectHandleI); } ObjectInformation info = new ObjectInformation(); // If the cache contains the object type's name, use it. Otherwise, query the type // for its name. Windows.ObjectTypesLock.AcquireShared(); try { if (Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { info.TypeName = Windows.ObjectTypes[thisHandle.ObjectTypeNumber]; } } finally { Windows.ObjectTypesLock.ReleaseShared(); } if (string.IsNullOrEmpty(info.TypeName)) { Win32.NtQueryObject( objectHandle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength ); if (retLength > 0) { using (MemoryAlloc otiMem = new MemoryAlloc(retLength)) { Win32.NtQueryObject( objectHandle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength ).ThrowIf(); ObjectTypeInformation oti = otiMem.ReadStruct <ObjectTypeInformation>(); UnicodeString str = oti.Name; //if (KProcessHacker.Instance != null) //str.Buffer = str.Buffer.Increment(otiMem.Memory.Decrement(baseAddress)); info.TypeName = str.Text; Windows.ObjectTypesLock.AcquireExclusive(); try { if (!Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { Windows.ObjectTypes.Add(thisHandle.ObjectTypeNumber, info.TypeName); } } finally { Windows.ObjectTypesLock.ReleaseExclusive(); } } } } if (!getName) { return(info); } // Get the object's name. If the object is a file we must take special // precautions so that we don't hang. if (string.Equals(info.TypeName, "File", StringComparison.OrdinalIgnoreCase)) { //if (KProcessHacker.Instance != null) //{ // // Use KProcessHacker for files to avoid hangs. // info.OrigName = KProcessHacker.Instance.GetHandleObjectName(process, handle); //} //else { // 0: No hack, query the thing normally. // 1: No hack, use NProcessHacker. // 2: Hack. int hackLevel = 1; // If we already tried to use NPH but it wasn't present, // skip to level 2. if (NphNotAvailable) { hackLevel = 2; } // Can't use NPH because XP had a bug where a thread hanging // on NtQueryObject couldn't be terminated. if (OSVersion.IsBelowOrEqual(WindowsVersion.XP)) { hackLevel = 2; } // On Windows 7 and above the hanging bug appears to have // been fixed. Query the object normally. // UPDATE: Not so. It still happens. //if (OSVersion.IsAboveOrEqual(WindowsVersion.Seven)) // hackLevel = 0; if (hackLevel == 1) { try { // Use NProcessHacker. using (MemoryAlloc oniMem = new MemoryAlloc(0x4000)) { NProcessHacker.PhQueryNameFileObject( objectHandle, oniMem, oniMem.Size, out retLength ).ThrowIf(); var oni = oniMem.ReadStruct <ObjectNameInformation>(); info.OrigName = oni.Name.Text; } } catch (DllNotFoundException) { hackLevel = 2; NphNotAvailable = true; } } if (hackLevel == 0) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } else if (hackLevel == 2) { // KProcessHacker and NProcessHacker not available. Fall back to using hack // (i.e. not querying the name at all if the access is 0x0012019f). if (thisHandle.GrantedAccess != 0x0012019f) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } } } } else { // Not a file. Query the object normally. info.OrigName = GetObjectNameNt(process, handle, objectHandle); } // Get a better name for the handle. try { switch (info.TypeName) { case "File": // Resolves \Device\HarddiskVolume1 into C:, for example. if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = FileUtils.GetFileName(info.OrigName); } break; case "Key": info.BestName = NativeUtils.FormatNativeKeyName(info.OrigName); break; case "Process": { int processId; using (NativeHandle <ProcessAccess> processHandle = new NativeHandle <ProcessAccess>(process, handle, OSVersion.MinProcessQueryInfoAccess)) { if ((processId = Win32.GetProcessId(processHandle)) == 0) { Win32.Throw(); } } info.BestName = (new ClientId(processId, 0)).GetName(false); } break; case "Thread": { int processId; int threadId; using (var threadHandle = new NativeHandle <ThreadAccess>(process, handle, OSVersion.MinThreadQueryInfoAccess)) { var basicInfo = ThreadHandle.FromHandle(threadHandle).GetBasicInformation(); threadId = basicInfo.ClientId.ThreadId; processId = basicInfo.ClientId.ProcessId; } info.BestName = (new ClientId(processId, threadId)).GetName(true); } break; case "TmEn": { using (NativeHandle <EnlistmentAccess> enHandleDup = new NativeHandle <EnlistmentAccess>(process, handle, EnlistmentAccess.QueryInformation)) using (EnlistmentHandle enHandle = EnlistmentHandle.FromHandle(enHandleDup)) { info.BestName = enHandle.BasicInformation.EnlistmentId.ToString("B"); } } break; case "TmRm": { using (var rmHandleDup = new NativeHandle <ResourceManagerAccess>(process, handle, ResourceManagerAccess.QueryInformation)) { var rmHandle = ResourceManagerHandle.FromHandle(rmHandleDup); info.BestName = rmHandle.Description; if (string.IsNullOrEmpty(info.BestName)) { info.BestName = rmHandle.Guid.ToString("B"); } } } break; case "TmTm": { using (NativeHandle <TmAccess> tmHandleDup = new NativeHandle <TmAccess>(process, handle, TmAccess.QueryInformation)) using (TmHandle tmHandle = TmHandle.FromHandle(tmHandleDup)) { info.BestName = FileUtils.GetFileName(FileUtils.GetFileName(tmHandle.LogFileName)); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = tmHandle.BasicInformation.TmIdentity.ToString("B"); } } } break; case "TmTx": { using (var transactionHandleDup = new NativeHandle <TransactionAccess>(process, handle, TransactionAccess.QueryInformation)) { TransactionHandle transactionHandle = TransactionHandle.FromHandle(transactionHandleDup); info.BestName = transactionHandle.Description; if (string.IsNullOrEmpty(info.BestName)) { info.BestName = transactionHandle.BasicInformation.TransactionId.ToString("B"); } } } break; case "Token": { using (var tokenHandleDup = new NativeHandle <TokenAccess>(process, handle, TokenAccess.Query)) using (TokenHandle tokenHandle = TokenHandle.FromHandle(tokenHandleDup)) using (tokenHandle.User) { info.BestName = tokenHandle.User.GetFullName(true) + ": 0x" + tokenHandle.Statistics.AuthenticationId; } } break; default: if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = info.OrigName; } else { info.BestName = null; } break; } } catch { if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = info.OrigName; } else { info.BestName = null; } } if (objectHandle != null) { objectHandle.Dispose(); } return(info); }
public static ObjectInformation GetHandleInfo(this SystemHandleEntry thisHandle, ProcessHandle process, bool getName) { IntPtr handle = new IntPtr(thisHandle.Handle); IntPtr objectHandleI; int retLength = 0; GenericHandle objectHandle = null; if (thisHandle.Handle == 0 || thisHandle.Handle == -1 || thisHandle.Handle == -2) { throw new WindowsException(NtStatus.InvalidHandle); } // Duplicate the handle if we're not using KPH if (KProcessHacker.Instance == null) { NtStatus status; if ((status = Win32.NtDuplicateObject( process, handle, ProcessHandle.Current, out objectHandleI, 0, 0, 0)) >= NtStatus.Error) { Win32.ThrowLastError(status); } objectHandle = new GenericHandle(objectHandleI); } ObjectInformation info = new ObjectInformation(); // If the cache contains the object type's name, use it. Otherwise, query the type // for its name. lock (Windows.ObjectTypes) { if (Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { info.TypeName = Windows.ObjectTypes[thisHandle.ObjectTypeNumber]; } else { int baseAddress = 0; if (KProcessHacker.Instance != null) { KProcessHacker.Instance.ZwQueryObject(process, handle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength, out baseAddress); } else { Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength); } if (retLength > 0) { using (MemoryAlloc otiMem = new MemoryAlloc(retLength)) { if (KProcessHacker.Instance != null) { if (KProcessHacker.Instance.ZwQueryObject(process, handle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength, out baseAddress) >= NtStatus.Error) { throw new Exception("ZwQueryObject failed."); } } else { if (Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength) >= NtStatus.Error) { throw new Exception("NtQueryObject failed."); } } var oti = otiMem.ReadStruct <ObjectTypeInformation>(); var str = oti.Name; if (KProcessHacker.Instance != null) { str.Buffer = str.Buffer.Increment(otiMem.Memory.Decrement(baseAddress)); } info.TypeName = str.Read(); Windows.ObjectTypes.Add(thisHandle.ObjectTypeNumber, info.TypeName); } } } } if (!getName) { return(info); } // Get the object's name. If the object is a file we must take special // precautions so that we don't hang. if (info.TypeName == "File") { if (KProcessHacker.Instance != null) { // Use KProcessHacker for files to avoid hangs. info.OrigName = KProcessHacker.Instance.GetHandleObjectName(process, handle); } else { // 0: No hack, query the thing normally. // 1: No hack, use NProcessHacker. // 2: Hack. int hackLevel = 1; // Can't use NPH because XP had a bug where a thread hanging // on NtQueryObject couldn't be terminated. if (OSVersion.IsBelowOrEqual(WindowsVersion.XP)) { hackLevel = 2; } // On Windows 7 and above the hanging bug appears to have // been fixed. Query the object normally. // UPDATE: Not so. It still happens. //if (OSVersion.IsAboveOrEqual(WindowsVersion.Seven)) // hackLevel = 0; if (hackLevel == 1) { try { // Use NProcessHacker. using (MemoryAlloc oniMem = new MemoryAlloc(0x4000)) { if (NProcessHacker.PhQueryNameFileObject( objectHandle, oniMem, oniMem.Size, out retLength) >= NtStatus.Error) { throw new Exception("PhQueryNameFileObject failed."); } var oni = oniMem.ReadStruct <ObjectNameInformation>(); info.OrigName = oni.Name.Read(); } } catch (DllNotFoundException) { hackLevel = 2; } } if (hackLevel == 0) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } else if (hackLevel == 2) { // KProcessHacker and NProcessHacker not available. Fall back to using hack // (i.e. not querying the name at all if the access is 0x0012019f). if ((int)thisHandle.GrantedAccess != 0x0012019f) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } } } } else { // Not a file. Query the object normally. info.OrigName = GetObjectNameNt(process, handle, objectHandle); } // Get a better name for the handle. try { switch (info.TypeName) { case "File": // Resolves \Device\Harddisk1 into C:, for example. if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = FileUtils.GetFileName(info.OrigName); } break; case "Key": info.BestName = NativeUtils.FormatNativeKeyName(info.OrigName); break; case "Process": { int processId; if (KProcessHacker.Instance != null) { processId = KProcessHacker.Instance.KphGetProcessId(process, handle); if (processId == 0) { throw new Exception("Invalid PID"); } } else { using (var processHandle = new NativeHandle <ProcessAccess>(process, handle, OSVersion.MinProcessQueryInfoAccess)) { if ((processId = Win32.GetProcessId(processHandle)) == 0) { Win32.ThrowLastError(); } } } info.BestName = (new ClientId(processId, 0)).GetName(false); } break; case "Thread": { int processId; int threadId; if (KProcessHacker.Instance != null) { threadId = KProcessHacker.Instance.KphGetThreadId(process, handle, out processId); if (threadId == 0 || processId == 0) { throw new Exception("Invalid TID or PID"); } } else { using (var threadHandle = new NativeHandle <ThreadAccess>(process, handle, OSVersion.MinThreadQueryInfoAccess)) { var basicInfo = ThreadHandle.FromHandle(threadHandle).GetBasicInformation(); threadId = basicInfo.ClientId.ThreadId; processId = basicInfo.ClientId.ProcessId; } } info.BestName = (new ClientId(processId, threadId)).GetName(true); } break; case "TmEn": { using (var enHandleDup = new NativeHandle <EnlistmentAccess>(process, handle, EnlistmentAccess.QueryInformation)) { var enHandle = EnlistmentHandle.FromHandle(enHandleDup); info.BestName = enHandle.GetBasicInformation().EnlistmentId.ToString("B"); } } break; case "TmRm": { using (var rmHandleDup = new NativeHandle <ResourceManagerAccess>(process, handle, ResourceManagerAccess.QueryInformation)) { var rmHandle = ResourceManagerHandle.FromHandle(rmHandleDup); info.BestName = rmHandle.GetDescription(); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = rmHandle.GetGuid().ToString("B"); } } } break; case "TmTm": { using (var tmHandleDup = new NativeHandle <TmAccess>(process, handle, TmAccess.QueryInformation)) { var tmHandle = TmHandle.FromHandle(tmHandleDup); info.BestName = FileUtils.GetFileName(FileUtils.GetFileName(tmHandle.GetLogFileName())); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = tmHandle.GetBasicInformation().TmIdentity.ToString("B"); } } } break; case "TmTx": { using (var transactionHandleDup = new NativeHandle <TransactionAccess>(process, handle, TransactionAccess.QueryInformation)) { var transactionHandle = TransactionHandle.FromHandle(transactionHandleDup); info.BestName = transactionHandle.GetDescription(); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = transactionHandle.GetBasicInformation().TransactionId.ToString("B"); } } } break; case "Token": { using (var tokenHandleDup = new NativeHandle <TokenAccess>(process, handle, TokenAccess.Query)) { var tokenHandle = TokenHandle.FromHandle(tokenHandleDup); var sid = tokenHandle.GetUser(); using (sid) info.BestName = sid.GetFullName(true) + ": 0x" + tokenHandle.GetStatistics().AuthenticationId.ToString(); } } break; default: if (info.OrigName != null && info.OrigName != "") { info.BestName = info.OrigName; } else { info.BestName = null; } break; } } catch { if (info.OrigName != null && info.OrigName != "") { info.BestName = info.OrigName; } else { info.BestName = null; } } if (objectHandle != null) { objectHandle.Dispose(); } return(info); }