Exemple #1
0
static void TaskManager_OnTabWndSelChange(void)
{
    int   i;
    HMENU hMenu;
    HMENU hOptionsMenu;
    HMENU hViewMenu;
    HMENU hSubMenu;

    WCHAR wszLargeIcons[255];
    WCHAR wszSmallIcons[255];
    WCHAR wszDetails[255];
    WCHAR wszWindows[255];
    WCHAR wszSelectColumns[255];
    WCHAR wszShow16bTasks[255];
    WCHAR wszOneGraphAllCPU[255];
    WCHAR wszOneGraphPerCPU[255];
    WCHAR wszCPUHistory[255];
    WCHAR wszShowKernelTimes[255];

    LoadStringW(hInst, IDS_VIEW_LARGE, wszLargeIcons, sizeof(wszLargeIcons)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_SMALL, wszSmallIcons, sizeof(wszSmallIcons)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_DETAILS, wszDetails, sizeof(wszDetails)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_WINDOWS, wszWindows, sizeof(wszWindows)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_SELECTCOLUMNS, wszSelectColumns, sizeof(wszSelectColumns)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_OPTIONS_SHOW16BITTASKS, wszShow16bTasks, sizeof(wszShow16bTasks)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_CPUHISTORY_ONEGRAPHALL, wszOneGraphAllCPU, sizeof(wszOneGraphAllCPU)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_CPUHISTORY_ONEGRAPHPERCPU, wszOneGraphPerCPU, sizeof(wszOneGraphPerCPU)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_CPUHISTORY, wszCPUHistory, sizeof(wszCPUHistory)/sizeof(WCHAR));
    LoadStringW(hInst, IDS_VIEW_SHOWKERNELTIMES, wszShowKernelTimes, sizeof(wszShowKernelTimes)/sizeof(WCHAR));

    hMenu = GetMenu(hMainWnd);
    hViewMenu = GetSubMenu(hMenu, 2);
    hOptionsMenu = GetSubMenu(hMenu, 1);
    TaskManagerSettings.ActiveTabPage = TabCtrl_GetCurSel(hTabWnd);
    for (i = GetMenuItemCount(hViewMenu) - 1; i > 2; i--) {
        hSubMenu = GetSubMenu(hViewMenu, i);
        if (hSubMenu)
            DestroyMenu(hSubMenu);
        RemoveMenu(hViewMenu, i, MF_BYPOSITION);
    }
    RemoveMenu(hOptionsMenu, 3, MF_BYPOSITION);
    switch (TaskManagerSettings.ActiveTabPage) {
    case 0:
        ShowWindow(hApplicationPage, SW_SHOW);
        ShowWindow(hProcessPage, SW_HIDE);
        ShowWindow(hPerformancePage, SW_HIDE);
        BringWindowToTop(hApplicationPage);
        AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_LARGE, wszLargeIcons);
        AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SMALL, wszSmallIcons);
        AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_DETAILS, wszDetails);

        if (GetMenuItemCount(hMenu) <= 4) {
            hSubMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_WINDOWSMENU));
            InsertMenuW(hMenu, 3, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hSubMenu, wszWindows);
            DrawMenuBar(hMainWnd);
        }
        if (TaskManagerSettings.View_LargeIcons)
            CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
        else if (TaskManagerSettings.View_SmallIcons)
            CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
        else
            CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
        /*
         * Give the application list control focus
         */
        SetFocus(hApplicationPageListCtrl);
        break;

    case 1:
        ShowWindow(hApplicationPage, SW_HIDE);
        ShowWindow(hProcessPage, SW_SHOW);
        ShowWindow(hPerformancePage, SW_HIDE);
        BringWindowToTop(hProcessPage);
        AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SELECTCOLUMNS, wszSelectColumns);
        AppendMenuW(hOptionsMenu, MF_STRING, ID_OPTIONS_SHOW16BITTASKS, wszShow16bTasks);
        if (TaskManagerSettings.Show16BitTasks)
            CheckMenuItem(hOptionsMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
        if (GetMenuItemCount(hMenu) > 4)
        {
            RemoveMenu(hMenu, 3, MF_BYPOSITION);
            DrawMenuBar(hMainWnd);
        }
        /*
         * Give the process list control focus
         */
        SetFocus(hProcessPageListCtrl);
        break;

    case 2:
        ShowWindow(hApplicationPage, SW_HIDE);
        ShowWindow(hProcessPage, SW_HIDE);
        ShowWindow(hPerformancePage, SW_SHOW);
        BringWindowToTop(hPerformancePage);
        if (GetMenuItemCount(hMenu) > 4) {
            RemoveMenu(hMenu, 3, MF_BYPOSITION);
            DrawMenuBar(hMainWnd);
        }
        hSubMenu = CreatePopupMenu();
        AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, wszOneGraphAllCPU);
        AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, wszOneGraphPerCPU);
        AppendMenuW(hViewMenu, MF_STRING|MF_POPUP, (UINT_PTR)hSubMenu, wszCPUHistory);
        AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, wszShowKernelTimes);
        if (TaskManagerSettings.ShowKernelTimes)
            CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
        else
            CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
        if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
            CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
        else
            CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
        /*
         * Give the tab control focus
         */
        SetFocus(hTabWnd);
        break;
    }
}
Exemple #2
0
VOID
BuildLogList(void)
{
    HKEY hKey;
    DWORD lpcName;
    DWORD dwIndex;
    DWORD dwMessageID;
    DWORD dwMaxKeyLength;
    WCHAR szModuleName[MAX_PATH];
    LPWSTR lpDisplayName;
    HANDLE hLibrary = NULL;

    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, EVENTLOG_BASE_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
    {
        return;
    }

    if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumLogs, &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
    {
        RegCloseKey(hKey);
        return;
    }

    if (!dwNumLogs)
    {
        RegCloseKey(hKey);
        return;
    }

    LogNames = HeapAlloc(GetProcessHeap(), 0, (dwNumLogs + 1) * sizeof(WCHAR*));

    if (!LogNames)
    {
        RegCloseKey(hKey);
        return;
    }

    for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
    {
        LogNames[dwIndex] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((dwMaxKeyLength + 1) * sizeof(WCHAR)));

        if (LogNames[dwIndex] != NULL)
        {
            lpcName = dwMaxKeyLength + 1;

            if (RegEnumKeyExW(hKey, dwIndex, LogNames[dwIndex], &lpcName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
            {
                lpDisplayName = NULL;

                ZeroMemory(szModuleName, sizeof(szModuleName));
                GetDisplayNameFile(LogNames[dwIndex], szModuleName);
                dwMessageID = GetDisplayNameID(LogNames[dwIndex]);

                hLibrary = LoadLibraryExW(szModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
                if (hLibrary != NULL)
                {
                    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, hLibrary, dwMessageID, 0, (LPWSTR)&lpDisplayName, 0, NULL);
                    FreeLibrary(hLibrary);
                }

                if (lpDisplayName)
                {
                    InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, lpDisplayName);
                }
                else
                {
                    InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, LogNames[dwIndex]);
                }

                LocalFree(lpDisplayName);
            }
        }
    }

    InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_SEPARATOR, ID_FIRST_LOG + dwIndex + 1, NULL);

    RegCloseKey(hKey);

    return;
}
Exemple #3
0
/*************************************************************************
 * Shell_MergeMenus				[SHELL32.67]
 */
HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
{	int		nItem;
	HMENU		hmSubMenu;
	BOOL		bAlreadySeparated;
	MENUITEMINFOW	miiSrc;
	WCHAR		szName[256];
	UINT		uTemp, uIDMax = uIDAdjust;

	TRACE("hmenu1=%p hmenu2=%p 0x%04x 0x%04x 0x%04x  0x%04x\n",
		 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);

	if (!hmDst || !hmSrc)
	{ return uIDMax;
	}

	nItem = GetMenuItemCount(hmDst);

	if (uInsert >= (UINT)nItem)	/* insert position inside menu? */
	{
	  uInsert = (UINT)nItem;	/* append on the end */
	  bAlreadySeparated = TRUE;
	}
	else
	{
	  bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);
	}

	if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
	{
	  /* Add a separator between the menus */
	  InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
	  bAlreadySeparated = TRUE;
	}


	/* Go through the menu items and clone them*/
	for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
	{
	  miiSrc.cbSize = sizeof(MENUITEMINFOW);
	  miiSrc.fMask =  MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;

	  /* We need to reset this every time through the loop in case menus DON'T have IDs*/
	  miiSrc.fType = MFT_STRING;
	  miiSrc.dwTypeData = szName;
	  miiSrc.dwItemData = 0;
	  miiSrc.cch = sizeof(szName)/sizeof(WCHAR);

	  if (!GetMenuItemInfoW(hmSrc, nItem, TRUE, &miiSrc))
	  {
	    continue;
	  }

/*	  TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask,  miiSrc.hSubMenu);
*/
	  if (miiSrc.fType & MFT_SEPARATOR)
	  {
	    /* This is a separator; don't put two of them in a row */
	    if (bAlreadySeparated)
	      continue;

	    bAlreadySeparated = TRUE;
	  }
	  else if (miiSrc.hSubMenu)
	  {
	    if (uFlags & MM_SUBMENUSHAVEIDS)
	    {
	      miiSrc.wID += uIDAdjust;			/* add uIDAdjust to the ID */

	      if (miiSrc.wID > uIDAdjustMax)		/* skip ID's higher uIDAdjustMax */
	        continue;

	      if (uIDMax <= miiSrc.wID)			/* remember the highest ID */
	        uIDMax = miiSrc.wID + 1;
	    }
	    else
	    {
	      miiSrc.fMask &= ~MIIM_ID;			/* Don't set IDs for submenus that didn't have them already */
	    }
	    hmSubMenu = miiSrc.hSubMenu;

	    miiSrc.hSubMenu = CreatePopupMenu();

	    if (!miiSrc.hSubMenu) return(uIDMax);

	    uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS);

	    if (uIDMax <= uTemp)
	      uIDMax = uTemp;

	    bAlreadySeparated = FALSE;
	  }
	  else						/* normal menu item */
	  {
	    miiSrc.wID += uIDAdjust;			/* add uIDAdjust to the ID */

	    if (miiSrc.wID > uIDAdjustMax)		/* skip ID's higher uIDAdjustMax */
	      continue;

	    if (uIDMax <= miiSrc.wID)			/* remember the highest ID */
	      uIDMax = miiSrc.wID + 1;

	    bAlreadySeparated = FALSE;
	  }

/*	  TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
*/
	  if (!InsertMenuItemW(hmDst, uInsert, TRUE, &miiSrc))
	  {
	    return(uIDMax);
	  }
	}

	/* Ensure the correct number of separators at the beginning of the
	inserted menu items*/
	if (uInsert == 0)
	{
	  if (bAlreadySeparated)
	  {
	    DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
	  }
	}
	else
	{
	  if (_SHIsMenuSeparator(hmDst, uInsert-1))
	  {
	    if (bAlreadySeparated)
	    {
	      DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
	    }
	  }
	  else
	  {
	    if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
	    {
	      /* Add a separator between the menus*/
	      InsertMenuW(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
	    }
	  }
	}
	return(uIDMax);
}
Exemple #4
0
/***********************************************************************
 *           OleUIAddVerbMenuW (OLEDLG.14)
 */
BOOL WINAPI OleUIAddVerbMenuW(IOleObject *object, LPCWSTR shorttype,
    HMENU hMenu, UINT uPos, UINT idmin, UINT idmax, BOOL addConvert, UINT idConvert, HMENU *ret_submenu)
{
    static const WCHAR spaceW[] = {' ',0};
    IEnumOLEVERB *enumverbs = NULL;
    WCHAR *rootname, *objecttype;
    LPOLESTR usertype = NULL;
    OLEVERB firstverb, verb;
    WCHAR resstrW[32]; /* should be enough */
    BOOL singleverb;
    HMENU submenu;

    TRACE("(%p, %s, %p, %d, %d, %d, %d, %d, %p)\n", object, debugstr_w(shorttype),
        hMenu, uPos, idmin, idmax, addConvert, idConvert, ret_submenu);

    if (ret_submenu)
        *ret_submenu = NULL;

    if (!hMenu || !ret_submenu)
        return FALSE;

    /* check if we can get verbs at all */
    if (object)
        IOleObject_EnumVerbs(object, &enumverbs);

    LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_OBJECT, resstrW, sizeof(resstrW)/sizeof(WCHAR));
    /* no object, or object without enumeration support */
    if (!object || (object && !enumverbs)) {
        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_GRAYED, idmin, resstrW);
        return FALSE;
    }

    /* root entry string */
    if (!shorttype && (IOleObject_GetUserType(object, USERCLASSTYPE_SHORT, &usertype) == S_OK))
        objecttype = usertype;
    else
        objecttype = (WCHAR*)shorttype;

    rootname = CoTaskMemAlloc((strlenW(objecttype) + strlenW(resstrW) + 2)*sizeof(WCHAR));
    strcpyW(rootname, objecttype);
    strcatW(rootname, spaceW);
    strcatW(rootname, resstrW);
    CoTaskMemFree(usertype);

    /* iterate through verbs */

    /* find first suitable verb */
    get_next_insertable_verb(enumverbs, idmin, idmax, &firstverb);
    singleverb = get_next_insertable_verb(enumverbs, idmin, idmax, &verb) != S_OK;

    if (singleverb && !addConvert) {
        WCHAR *str = CoTaskMemAlloc((strlenW(rootname) + strlenW(firstverb.lpszVerbName) + 2)*sizeof(WCHAR));

        strcpyW(str, firstverb.lpszVerbName);
        strcatW(str, spaceW);
        strcatW(str, rootname);

        RemoveMenu(hMenu, uPos, MF_BYPOSITION);
        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idmin, str);
        CoTaskMemFree(firstverb.lpszVerbName);
        CoTaskMemFree(rootname);
        CoTaskMemFree(str);
        IEnumOLEVERB_Release(enumverbs);
        return TRUE;
    }

    submenu = CreatePopupMenu();
    insert_verb_to_menu(submenu, idmin, &firstverb);
    CoTaskMemFree(firstverb.lpszVerbName);

    if (!singleverb) {
        insert_verb_to_menu(submenu, idmin, &verb);
        CoTaskMemFree(verb.lpszVerbName);
    }

    while (get_next_insertable_verb(enumverbs, idmin, idmax, &verb) == S_OK) {
        insert_verb_to_menu(submenu, idmin, &verb);
        CoTaskMemFree(verb.lpszVerbName);
    }

    /* convert verb is at the bottom of a popup, separated from verbs */
    if (addConvert) {
        LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_CONVERT, resstrW, sizeof(resstrW)/sizeof(WCHAR));
        InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
        InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_STRING, idConvert, resstrW);
    }

    if (submenu)
        *ret_submenu = submenu;

    /* now submenu is ready, add root entry to original menu, attach submenu */
    InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)submenu, rootname);
    IEnumOLEVERB_Release(enumverbs);
    CoTaskMemFree(rootname);
    return TRUE;
}
Exemple #5
0
static void insert_verb_to_menu(HMENU menu, UINT idmin, const OLEVERB *verb)
{
    InsertMenuW(menu, ~0, verb->fuFlags | MF_BYPOSITION | MF_STRING, verb->lVerb + idmin, verb->lpszVerbName);
}
Exemple #6
0
/***********************************************************************
 *           OleUIAddVerbMenuW (OLEDLG.14)
 */
BOOL WINAPI OleUIAddVerbMenuW(IOleObject *object, LPCWSTR shorttype,
    HMENU hMenu, UINT uPos, UINT idmin, UINT idmax, BOOL addConvert, UINT idConvert, HMENU *ret_submenu)
{
    IEnumOLEVERB *enumverbs = NULL;
    LPOLESTR usertype = NULL;
    OLEVERB firstverb, verb;
    WCHAR *objecttype;
    WCHAR resstrW[32]; /* should be enough */
    DWORD_PTR args[2];
    BOOL singleverb;
    HMENU submenu;
    WCHAR *str;

    TRACE("(%p, %s, %p, %d, %d, %d, %d, %d, %p)\n", object, debugstr_w(shorttype),
        hMenu, uPos, idmin, idmax, addConvert, idConvert, ret_submenu);

    if (ret_submenu)
        *ret_submenu = NULL;

    if (!hMenu || !ret_submenu)
        return FALSE;

    /* check if we can get verbs at all */
    if (object)
        IOleObject_EnumVerbs(object, &enumverbs);

    LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_OBJECT, resstrW, sizeof(resstrW)/sizeof(WCHAR));
    /* no object, or object without enumeration support */
    if (!object || !enumverbs) {
        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_GRAYED, idmin, resstrW);
        return FALSE;
    }

    /* root entry string */
    if (!shorttype && (IOleObject_GetUserType(object, USERCLASSTYPE_SHORT, &usertype) == S_OK))
        objecttype = usertype;
    else
        objecttype = (WCHAR*)shorttype;

    /* iterate through verbs */

    /* find first suitable verb */
    get_next_insertable_verb(enumverbs, idmin, idmax, &firstverb);
    singleverb = get_next_insertable_verb(enumverbs, idmin, idmax, &verb) != S_OK;

    if (singleverb && !addConvert) {
        LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_SINGLEVERB_OBJECT, resstrW, sizeof(resstrW)/sizeof(WCHAR));

        args[0] = (DWORD_PTR)firstverb.lpszVerbName;
        args[1] = (DWORD_PTR)objecttype;

        FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY,
            resstrW, 0, 0, (WCHAR*)&str, 0, (__ms_va_list*)args);

        RemoveMenu(hMenu, uPos, MF_BYPOSITION);
        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idmin, str);
        CoTaskMemFree(firstverb.lpszVerbName);
        HeapFree(GetProcessHeap(), 0, str);
        IEnumOLEVERB_Release(enumverbs);
        CoTaskMemFree(usertype);
        return TRUE;
    }

    submenu = CreatePopupMenu();
    insert_verb_to_menu(submenu, idmin, &firstverb);
    CoTaskMemFree(firstverb.lpszVerbName);

    if (!singleverb) {
        insert_verb_to_menu(submenu, idmin, &verb);
        CoTaskMemFree(verb.lpszVerbName);
    }

    while (get_next_insertable_verb(enumverbs, idmin, idmax, &verb) == S_OK) {
        insert_verb_to_menu(submenu, idmin, &verb);
        CoTaskMemFree(verb.lpszVerbName);
    }

    /* convert verb is at the bottom of a popup, separated from verbs */
    if (addConvert) {
        LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_CONVERT, resstrW, sizeof(resstrW)/sizeof(WCHAR));
        InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
        InsertMenuW(submenu, ~0, MF_BYPOSITION|MF_STRING, idConvert, resstrW);
    }

    if (submenu)
        *ret_submenu = submenu;

    /* now submenu is ready, add root entry to original menu, attach submenu */
    LoadStringW(OLEDLG_hInstance, IDS_VERBMENU_OBJECT_WITH_NAME, resstrW, sizeof(resstrW)/sizeof(WCHAR));

    args[0] = (DWORD_PTR)objecttype;
    FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_ARGUMENT_ARRAY,
        resstrW, 0, 0, (WCHAR*)&str, 0, (__ms_va_list*)args);

    InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)submenu, str);
    HeapFree(GetProcessHeap(), 0, str);
    IEnumOLEVERB_Release(enumverbs);
    CoTaskMemFree(usertype);
    return TRUE;
}