public void ToSecureStringTest(string sval) { var ms = new SafeCoTaskMemString(sval); var ss = ms.DangerousGetHandle().ToSecureString(); if (sval != null) { Assert.That(ss, Is.Not.Null); Assert.That(ss.Length, Is.EqualTo(sval.Length)); var s = ss.ToInsecureString(); Assert.That(s, Is.EqualTo(sval)); if (sval.Length > 1) { ss = ms.DangerousGetHandle().ToSecureString(1); Assert.That(ss, Is.Not.Null); Assert.That(ss.Length, Is.EqualTo(1)); s = ss.ToInsecureString(); Assert.That(s, Is.EqualTo(sval.Substring(0, 1))); } } else { Assert.That(ss, Is.Null); } }
private static string GetCommandString(Shell32.IContextMenu cMenu, uint offset, Shell32.GCS flags = Shell32.GCS.GCS_VERBW) { if (offset > 5000) { // Hackish workaround to avoid an AccessViolationException on some items, // notably the "Run with graphic processor" menu item of NVidia cards return(null); } SafeCoTaskMemString commandString = null; try { commandString = new SafeCoTaskMemString(512); cMenu.GetCommandString(new IntPtr(offset), flags, IntPtr.Zero, commandString, (uint)commandString.Capacity - 1); Debug.WriteLine("Verb {0}: {1}", offset, commandString); return(commandString.ToString()); } catch (Exception ex) when(ex is InvalidCastException || ex is ArgumentException) { // TODO: investigate this.. Debug.WriteLine(ex); return(null); } catch (Exception ex) when(ex is COMException || ex is NotImplementedException) { // Not every item has an associated verb return(null); } finally { commandString?.Dispose(); } }
public void PathCchFindExtensionTest() { var sb = new SafeCoTaskMemString(@"C:\Temp\dog.txt", 64); Assert.That(PathCchFindExtension((IntPtr)sb, sb.Capacity, out var ptr), Is.EqualTo((HRESULT)0)); Assert.That(ptr, Is.EqualTo(sb.DangerousGetHandle().Offset(22))); }
public AuthenticationBuffer(SecureString userName, SecureString password) { var pUserName = new SafeCoTaskMemString(userName); var pPassword = new SafeCoTaskMemString(password); Init(0, pUserName, pPassword); }
public AuthenticationBuffer(string userName, string password) { var pUserName = new SafeCoTaskMemString(userName ?? ""); var pPassword = new SafeCoTaskMemString(password ?? ""); Init(0, pUserName, pPassword); }
private static string GetCommandString(Shell32.IContextMenu cMenu, uint offset, Shell32.GCS flags = Shell32.GCS.GCS_VERBW) { SafeCoTaskMemString commandString = null; try { commandString = new SafeCoTaskMemString(512); cMenu.GetCommandString(new IntPtr(offset), flags, IntPtr.Zero, commandString, (uint)commandString.Capacity - 1); Debug.WriteLine("Verb {0}: {1}", offset, commandString); return(commandString.ToString()); } catch (Exception ex) when(ex is InvalidCastException || ex is ArgumentException) { // TODO: investigate this.. Debug.WriteLine(ex); return(null); } catch (Exception ex) when(ex is COMException || ex is NotImplementedException) { // Not every item has an associated verb return(null); } finally { commandString?.Dispose(); } }
public unsafe void ReadFileExTest() { using (var tmp = new TempFile(Kernel32.FileAccess.FILE_GENERIC_READ, FileShare.Read)) using (var sb = new SafeCoTaskMemString(100, CharSet.Ansi)) { var read = 0U; var nativeOverlapped = new NativeOverlapped(); var b = ReadFileEx(tmp.hFile, (byte *)(IntPtr)sb, (uint)sb.Capacity, &nativeOverlapped, fnComplete); if (!b) { TestContext.WriteLine($"ReadFileEx:{Win32Error.GetLastError()}"); } Assert.That(b); SleepEx(0, true); //if (read < sb.Capacity) Marshal.WriteInt16((IntPtr)sb, (int)read, '\0'); //Assert.That(read, Is.Not.Zero.And.LessThanOrEqualTo(sb.Capacity)); //Assert.That((string)sb, Is.EqualTo(tmpstr)); unsafe void fnComplete(uint dwErrorCode, uint dwNumberOfBytesTransfered, NativeOverlapped *lpOverlapped) { if (dwErrorCode == 0) { GetOverlappedResult(tmp.hFile, lpOverlapped, out read, false); } else { read = dwNumberOfBytesTransfered; } } } }
public void ToStringTest() { const int sz = 100; var s = new SafeCoTaskMemString(new string('x', sz)); Assert.That(s.ToString(), Is.EqualTo(new string('x', sz))); }
public void PathCchSkipRootTest() { var sb = new SafeCoTaskMemString(TestCaseSources.TempDirWhack, 64); Assert.That(PathCchSkipRoot((IntPtr)sb, out var end), Is.EqualTo((HRESULT)0)); Assert.That(end, Is.EqualTo(sb.DangerousGetHandle().Offset(6))); }
/// <summary>Shows the dialog box to let the user browse for and select a folder.</summary> /// <param name="parentWindowHandle">The HWND of the parent window.</param> /// <returns>The selected folder or <c>null</c> if no folder was selected by the user.</returns> protected override bool RunDialog(IntPtr parentWindowHandle) { // Setup BROWSEINFO.dwFlag value EnumFlagIndexer <BrowseInfoFlag> browseInfoFlag = BrowseInfoFlag.BIF_SHAREABLE; browseInfoFlag[BrowseInfoFlag.BIF_NEWDIALOGSTYLE] = Application.OleRequired() == ApartmentState.STA; browseInfoFlag[BrowseInfoFlag.BIF_DONTGOBELOWDOMAIN] = HideDomainFolders; browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFILEJUNCTIONS] = ShowFileJunctions; browseInfoFlag[BrowseInfoFlag.BIF_RETURNONLYFSDIRS] = LocalFileSystemOnly; browseInfoFlag[BrowseInfoFlag.BIF_NONEWFOLDERBUTTON] = !ShowNewFolderButton; browseInfoFlag[BrowseInfoFlag.BIF_EDITBOX | BrowseInfoFlag.BIF_VALIDATE] = ShowFolderPathEditBox; switch (BrowseOption) { case FolderBrowserDialogOptions.Folders: break; case FolderBrowserDialogOptions.FoldersAndFiles: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEINCLUDEFILES; break; case FolderBrowserDialogOptions.Computers: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEFORCOMPUTER; RootFolder = defaultComputersFolder; break; case FolderBrowserDialogOptions.Printers: browseInfoFlag |= BrowseInfoFlag.BIF_BROWSEFORPRINTER; RootFolder = defaultPrintersFolder; break; default: throw new ArgumentOutOfRangeException(); } // Setup the BROWSEINFO structure var dn = new SafeCoTaskMemString(Kernel32.MAX_PATH); var bi = new BROWSEINFO(parentWindowHandle, rootPidl.DangerousGetHandle(), Description, browseInfoFlag, OnBrowseEvent, dn.DangerousGetHandle()); // Show the dialog pidl = SHBrowseForFolder(ref bi); href = default(HandleRef); if (pidl.IsInvalid) { return(false); } if (browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFORPRINTER] || browseInfoFlag[BrowseInfoFlag.BIF_BROWSEFORCOMPUTER]) { SelectedItem = bi.DisplayName; } else { SelectedItem = GetNameForPidl(pidl); } return(true); }
public void SafeCoTaskMemStringTest1() { const int sz = 100; var s = new SafeCoTaskMemString(sz); Assert.That(s.Capacity, Is.EqualTo(sz)); Assert.That((string)s, Is.EqualTo(string.Empty)); s = new SafeCoTaskMemString(sz, System.Runtime.InteropServices.CharSet.Ansi); Assert.That(s.Capacity, Is.EqualTo(sz)); Assert.That((string)s, Is.EqualTo(string.Empty)); }
public void InstallApplicationTest() { var id = new INSTALLDATA { Type = INSTALLSPECTYPE.FILEEXT }; var pExt = new SafeCoTaskMemString("*.jpg"); id.Spec = new INSTALLSPEC { FileExt = (IntPtr)pExt }; Assert.That(InstallApplication(id), ResultIs.Successful); }
public void PathCchRemoveBackslashExTest() { var sb = new SafeCoTaskMemString(@"C:\Temp\", 64); Assert.That(PathCchRemoveBackslashEx((IntPtr)sb, sb.Capacity, out var end, out var rem), Is.EqualTo((HRESULT)0)); Assert.That(sb.ToString(), Is.EqualTo(@"C:\Temp")); Assert.That(end, Is.EqualTo(sb.DangerousGetHandle().Offset(14))); sb = new SafeCoTaskMemString(@"C:\Temp", 64); Assert.That(PathCchRemoveBackslashEx((IntPtr)sb, sb.Capacity, out end, out rem), Is.EqualTo((HRESULT)HRESULT.S_FALSE)); Assert.That(sb.ToString(), Is.EqualTo(@"C:\Temp")); Assert.That(end, Is.EqualTo(sb.DangerousGetHandle().Offset(14))); }
internal BackgroundCopyException(IBackgroundCopyError err) { const uint lang = 0x1; // LANG_NEUTRAL, SUBLANG_DEFAULT err.GetError(out ctx, out code); try { ctxDesc = err.GetErrorContextDescription(lang); } catch { ctxDesc = SafeCoTaskMemString.Null; } try { errDesc = err.GetErrorDescription(lang); } catch { errDesc = SafeCoTaskMemString.Null; } try { protocol = err.GetProtocol(); } catch { protocol = SafeCoTaskMemString.Null; } iVal = err.GetFile(); }
public void PathCchAddBackslashExTest2() { var sb = new SafeCoTaskMemString(TestCaseSources.TempDirWhack, 64); Assert.That(PathCchAddBackslashEx((IntPtr)sb, sb.Capacity, out var end, out var rem), Is.EqualTo((HRESULT)HRESULT.S_FALSE)); Assert.That(sb.ToString(), Is.EqualTo(TestCaseSources.TempDirWhack)); Assert.That(end, Is.EqualTo(sb.DangerousGetHandle().Offset(sb.Length * 2))); sb = new SafeCoTaskMemString(TestCaseSources.TempDir, 64); Assert.That(PathCchAddBackslashEx((IntPtr)sb, sb.Size, out end, out rem), Is.EqualTo((HRESULT)0)); Assert.That(sb.ToString(), Is.EqualTo(TestCaseSources.TempDirWhack)); Assert.That(end, Is.EqualTo(sb.DangerousGetHandle().Offset(sb.Length * 2))); }
public void FindTextTest() { using var wnd = new DlgWin(RegisterWindowMessage(FINDMSGSTRING)); var fw = new SafeCoTaskMemString(261); var fr = new FINDREPLACE { lStructSize = (uint)Marshal.SizeOf(typeof(FINDREPLACE)), hwndOwner = wnd.MessageWindowHandle, lpstrFindWhat = (IntPtr)fw, wFindWhatLen = (ushort)fw.Length, }; Assert.That(wnd.hdlg = FindText(ref fr), Is.True); }
private void Init(CredUI.CredPackFlags flags, SafeCoTaskMemString pUserName, SafeCoTaskMemString pPassword) { if (!CredUI.CredPackAuthenticationBuffer(flags, (IntPtr)pUserName, (IntPtr)pPassword, IntPtr.Zero, ref bufferSize) && Marshal.GetLastWin32Error() == 122) /*ERROR_INSUFFICIENT_BUFFER*/ { buffer = Marshal.AllocCoTaskMem(bufferSize); if (!CredUI.CredPackAuthenticationBuffer(flags, (IntPtr)pUserName, (IntPtr)pPassword, buffer, ref bufferSize)) { throw new Win32Exception(); } } else { throw new Win32Exception(); } }
public void SafeCoTaskMemStringTest2() { const int sz = 100; var ss = new SecureString(); foreach (var c in new string('x', sz)) ss.AppendChar(c); var s = new SafeCoTaskMemString(ss); Assert.That(s.Capacity, Is.EqualTo(sz + 1)); Assert.That((string)s, Is.EqualTo(new string('x', sz))); ss = null; s = new SafeCoTaskMemString(ss, CharSet.Ansi); Assert.That((string)s, Is.Null); Assert.That(s.Capacity, Is.Zero); }
public void SaferGetSetLevelInformationTest() { Assert.That(SaferCreateLevel(SAFER_SCOPEID.SAFER_SCOPEID_USER, SAFER_LEVELID.SAFER_LEVELID_NORMALUSER, SAFER_LEVEL_CREATE_FLAGS.SAFER_LEVEL_OPEN, out var hLvl), ResultIs.Successful); using (hLvl) { //using (var str = new SafeCoTaskMemString("Description")) using (var retstr = new SafeCoTaskMemString(1024)) { //Assert.That(SaferSetLevelInformation(hLvl, SAFER_OBJECT_INFO_CLASS.SaferObjectDescription, str, str.Size), ResultIs.Successful); Assert.That(SaferGetLevelInformation(hLvl, SAFER_OBJECT_INFO_CLASS.SaferObjectDescription, retstr, retstr.Size, out _), ResultIs.Successful); //Assert.That(retstr.ToString(), Is.EqualTo(str.ToString())); TestContext.WriteLine(retstr); } } }
public void GetOpenFileNameTest() { using var fn = new SafeCoTaskMemString(261); var ofn = new OPENFILENAME { lStructSize = (uint)Marshal.SizeOf(typeof(OPENFILENAME)), lpstrFile = (IntPtr)fn, nMaxFile = (uint)fn.Capacity, lpstrFilter = "All\0*.*\0Text\0*.txt\0", nFilterIndex = 1, Flags = OFN.OFN_PATHMUSTEXIST | OFN.OFN_FILEMUSTEXIST }; Assert.That(GetOpenFileName(ref ofn), Is.True); Assert.That(ofn.lpstrFilter.Length, Is.GreaterThan(0)); }
public void LoadCustomFontsTest() { var loader = new FontLoader(); Instance.RegisterFontCollectionLoader(loader); try { using var pDir = new SafeCoTaskMemString(fontDir); using var pColl = ComReleaserFactory.Create(Instance.CreateCustomFontCollection(loader, pDir, pDir.Size)); EnumFonts(pColl.Item); } finally { Instance.UnregisterFontCollectionLoader(loader); } }
public void UnPack(bool decryptProtectedCredentials, out SecureString userName, out SecureString domainName, out SecureString password) { var pUserName = new SafeCoTaskMemString(CRED_MAX_USERNAME_LENGTH); var pDomainName = new SafeCoTaskMemString(CRED_MAX_USERNAME_LENGTH); var pPassword = new SafeCoTaskMemString(CREDUI_MAX_PASSWORD_LENGTH); var userNameSize = pUserName.CharCapacity; var domainNameSize = pDomainName.CharCapacity; var passwordSize = pPassword.CharCapacity; if (!CredUnPackAuthenticationBuffer(decryptProtectedCredentials ? CredPackFlags.CRED_PACK_PROTECTED_CREDENTIALS : 0x0, buffer, bufferSize, (IntPtr)pUserName, ref userNameSize, (IntPtr)pDomainName, ref domainNameSize, (IntPtr)pPassword, ref passwordSize)) { throw new Win32Exception(); } userName = pUserName.DangerousGetHandle().ToSecureString(); domainName = pDomainName.DangerousGetHandle().ToSecureString(); password = pPassword.DangerousGetHandle().ToSecureString(); }
public void UnPack(bool decryptProtectedCredentials, out SecureString userName, out SecureString domainName, out SecureString password) { var pUserName = new SafeCoTaskMemString(CredUI.CRED_MAX_USERNAME_LENGTH); var pDomainName = new SafeCoTaskMemString(CredUI.CRED_MAX_USERNAME_LENGTH); var pPassword = new SafeCoTaskMemString(CredUI.CREDUI_MAX_PASSWORD_LENGTH); int userNameSize = pUserName.Size; int domainNameSize = pDomainName.Size; int passwordSize = pPassword.Size; if (!CredUI.CredUnPackAuthenticationBuffer(decryptProtectedCredentials ? 0x1 : 0x0, buffer, bufferSize, (IntPtr)pUserName, ref userNameSize, (IntPtr)pDomainName, ref domainNameSize, (IntPtr)pPassword, ref passwordSize)) { throw new Win32Exception(); } userName = pUserName.DangerousGetHandle().ToSecureString(); domainName = pDomainName.DangerousGetHandle().ToSecureString(); password = pPassword.DangerousGetHandle().ToSecureString(); }
public void SafeCoTaskMemStringTest() { const int sz = 100; var cs = new string('x', sz); var s = new SafeCoTaskMemString(cs); Assert.That(s.Capacity, Is.EqualTo(sz + 1)); Assert.That((string)s, Is.EqualTo(cs)); Assert.That((IntPtr)s, Is.Not.EqualTo(IntPtr.Zero)); s = new SafeCoTaskMemString(cs, System.Runtime.InteropServices.CharSet.Ansi); Assert.That(s.Capacity, Is.EqualTo(sz + 1)); Assert.That((string)s, Is.EqualTo(cs)); s = new SafeCoTaskMemString((string)null); Assert.That(s.Capacity, Is.EqualTo(0)); Assert.That((string)s, Is.Null); Assert.That((IntPtr)s, Is.EqualTo(IntPtr.Zero)); }
public void CreateReadFileTest() { var rofn = CreateTempFile(); using (var f = CreateFile(rofn, Kernel32.FileAccess.GENERIC_READ, FileShare.Read, null, FileMode.Open, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)) { var sb = new SafeCoTaskMemString(100, CharSet.Ansi); var b = ReadFile(f, (IntPtr)sb, (uint)sb.Capacity, out var read, IntPtr.Zero); if (!b) { TestContext.WriteLine($"ReadFile:{Win32Error.GetLastError()}"); } Assert.That(b); if (read < sb.Capacity) { Marshal.WriteInt16((IntPtr)sb, (int)read, '\0'); } Assert.That(read, Is.Not.Zero.And.LessThanOrEqualTo(sb.Capacity)); Assert.That((string)sb, Is.EqualTo(tmpstr)); b = SetFilePointerEx(f, 0, out var pos, SeekOrigin.Begin); if (!b) { TestContext.WriteLine($"SetFilePointerEx:{Win32Error.GetLastError()}"); } Assert.That(b); Assert.That(pos, Is.Zero); var bytes = new byte[100]; b = ReadFile(f, bytes, (uint)bytes.Length, out read, IntPtr.Zero); if (!b) { TestContext.WriteLine($"ReadFile:{Win32Error.GetLastError()}"); } Assert.That(b); Assert.That(read, Is.Not.Zero.And.LessThanOrEqualTo(bytes.Length)); Assert.That(Encoding.ASCII.GetString(bytes, 0, (int)read), Is.EqualTo(tmpstr)); } }
public void SafeResourceIdTest3() { const string s = "Test"; var sptr = new SafeCoTaskMemString(s); var r = new SafeResourceId((IntPtr)sptr); sptr.Dispose(); Assert.That(r.IsInvalid, Is.False); Assert.That(r.ToString(), Is.EqualTo(s)); Assert.That((string)r, Is.EqualTo(s)); Assert.That((int)r, Is.EqualTo(0)); const int i = 5; r = (IntPtr)i; Assert.That(r.Equals((IntPtr)i)); Assert.That(r.IsInvalid, Is.False); Assert.That(r.ToString(), Does.StartWith("#")); Assert.That((string)r, Does.StartWith("#")); Assert.That((int)r, Is.EqualTo(i)); Assert.That(((IntPtr)r).ToInt32(), Is.EqualTo(i)); }
public void CreateWriteFileTest() { using (var f = CreateFile(Path.GetTempFileName(), Kernel32.FileAccess.GENERIC_WRITE, FileShare.Write, null, FileMode.OpenOrCreate, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)) { var txt = "Some text to push."; var bytes = txt.GetBytes(false); var b = WriteFile(f, bytes, (uint)bytes.Length, out var written, IntPtr.Zero); if (!b) { TestContext.WriteLine($"WriteFile:{Win32Error.GetLastError()}"); } Assert.That(b); Assert.That(written, Is.EqualTo(bytes.Length)); var ptr = new SafeCoTaskMemString(" More text to push."); b = WriteFile(f, (IntPtr)ptr, (uint)ptr.Capacity, out written, IntPtr.Zero); if (!b) { TestContext.WriteLine($"WriteFile:{Win32Error.GetLastError()}"); } Assert.That(b); Assert.That(written, Is.EqualTo(ptr.Capacity)); } }
public void QueryTest([Values] CMF cmf) { using var pshi = ComReleaserFactory.Create(SHCreateItemFromParsingName <IShellItem>(TestCaseSources.WordDoc)); using var pcm = ComReleaserFactory.Create(pshi.Item.BindToHandler <IContextMenu>(null, BHID.BHID_SFUIObject.Guid())); using var hmenu = CreatePopupMenu(); Assert.That(pcm.Item.QueryContextMenu(hmenu, 0, 1, int.MaxValue, cmf), ResultIs.Successful); var miis = MenuItemInfo.GetMenuItems(hmenu); using var memstr = new SafeCoTaskMemString(1024, CharSet.Ansi); for (int i = 0; i < miis.Length; i++) { ShowMII(miis[i], i); } if (cmf == CMF.CMF_NORMAL) { var oid = miis.First(m => m.Verb == "properties").Id; var cix = new CMINVOKECOMMANDINFOEX((int)oid - 1); pcm.Item.InvokeCommand(cix); } void ShowMII(MenuItemInfo mii, int c, int indent = 0) { mii.Verb = mii.Type == MenuItemType.MFT_STRING && pcm.Item.GetCommandString((IntPtr)(int)(mii.Id - 1), GCS.GCS_VERBA, default, memstr, memstr.Size) == HRESULT.S_OK ? memstr.ToString() : "";
public void CredWriteTest() { const string targetName = "my.urn.pri"; using (var target = new SafeCoTaskMemString(targetName, System.Runtime.InteropServices.CharSet.Auto)) using (var user = new SafeCoTaskMemString("*****@*****.**", System.Runtime.InteropServices.CharSet.Auto)) using (var pwd = new SafeCoTaskMemString("asldfjua(#)$#$Jdf-0934390".ToSecureString(), System.Runtime.InteropServices.CharSet.Auto)) { var cred = new CREDENTIAL { Type = CRED_TYPE.CRED_TYPE_GENERIC, Persist = CRED_PERSIST.CRED_PERSIST_LOCAL_MACHINE, TargetName = (IntPtr)target, UserName = (IntPtr)user, CredentialBlob = (IntPtr)pwd, CredentialBlobSize = pwd.Size, }; Assert.That(CredWrite(cred, 0), ResultIs.Successful); try { //Assert.That(CredGetTargetInfo(target, 1, out var mem), ResultIs.Successful); const string credToProtect = targetName; var sb = new System.Text.StringBuilder(256); var sz = (uint)sb.Capacity; Assert.That(CredProtect(true, credToProtect, (uint)credToProtect.Length, sb, ref sz, out var type), ResultIs.Successful); TestContext.Write(sb); Assert.That(CredIsProtected(sb.ToString(), out var type2), Is.True); Assert.That(type, Is.EqualTo(type2)); } finally { Assert.That(CredDelete(targetName, CRED_TYPE.CRED_TYPE_GENERIC), ResultIs.Successful); } } }
private static void EnumMenuItems( Shell32.IContextMenu cMenu, HMENU hMenu, List <Win32ContextMenuItem> menuItemsResult, Func <string, bool> itemFilter = null) { var itemCount = User32.GetMenuItemCount(hMenu); var mii = new User32.MENUITEMINFO(); mii.cbSize = (uint)Marshal.SizeOf(mii); mii.fMask = User32.MenuItemInfoMask.MIIM_BITMAP | User32.MenuItemInfoMask.MIIM_FTYPE | User32.MenuItemInfoMask.MIIM_STRING | User32.MenuItemInfoMask.MIIM_ID | User32.MenuItemInfoMask.MIIM_SUBMENU; for (uint ii = 0; ii < itemCount; ii++) { var menuItem = new ContextMenuItem(); var container = new SafeCoTaskMemString(512); mii.dwTypeData = (IntPtr)container; mii.cch = (uint)container.Capacity - 1; // https://devblogs.microsoft.com/oldnewthing/20040928-00/?p=37723 var retval = User32.GetMenuItemInfo(hMenu, ii, true, ref mii); if (!retval) { container.Dispose(); continue; } menuItem.Type = (MenuItemType)mii.fType; menuItem.ID = (int)(mii.wID - 1); // wID - idCmdFirst if (menuItem.Type == MenuItemType.MFT_STRING) { Debug.WriteLine("Item {0} ({1}): {2}", ii, mii.wID, mii.dwTypeData); menuItem.Label = mii.dwTypeData; menuItem.CommandString = GetCommandString(cMenu, mii.wID - 1); if (itemFilter != null && (itemFilter(menuItem.CommandString) || itemFilter(menuItem.Label))) { // Skip items implemented in UWP container.Dispose(); continue; } if (mii.hbmpItem != HBITMAP.NULL && !Enum.IsDefined(typeof(HBITMAP_HMENU), ((IntPtr)mii.hbmpItem).ToInt64())) { var bitmap = GetBitmapFromHBitmap(mii.hbmpItem); if (bitmap != null) { menuItem.Icon = bitmap; } } if (mii.hSubMenu != HMENU.NULL) { Debug.WriteLine("Item {0}: has submenu", ii); var subItems = new List <Win32ContextMenuItem>(); try { (cMenu as Shell32.IContextMenu2)?.HandleMenuMsg((uint)User32.WindowMessage.WM_INITMENUPOPUP, (IntPtr)mii.hSubMenu, new IntPtr(ii)); } catch (NotImplementedException) { // Only for dynamic/owner drawn? (open with, etc) } EnumMenuItems(cMenu, mii.hSubMenu, subItems, itemFilter); menuItem.SubItems = subItems; Debug.WriteLine("Item {0}: done submenu", ii); } } else { Debug.WriteLine("Item {0}: {1}", ii, mii.fType.ToString()); } container.Dispose(); menuItemsResult.Add(menuItem); } }