⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
         {
            Menu = UserGetMenuObject(CurItem->hSubMenu);
            if (NULL != Menu)
            {
               ret = IntGetMenuItemByFlag(Menu, uSearchBy, fFlag,
                                          MenuItem, PrevMenuItem);
               if (-1 != ret)
               {
                  return ret;
               }
            }
         }
         PrevItem = CurItem;
         CurItem = CurItem->Next;
         p++;
      }
   }
   return -1;
}


int FASTCALL
IntInsertMenuItemToList(PMENU_OBJECT Menu, PMENU_ITEM MenuItem, int pos)
{
   PMENU_ITEM CurItem;
   PMENU_ITEM LastItem = NULL;
   UINT npos = 0;

   CurItem = Menu->MenuItemList;
   if(pos <= -1)
   {
      while(CurItem)
      {
         LastItem = CurItem;
         CurItem = CurItem->Next;
         npos++;
      }
   }
   else
   {
      while(CurItem && (pos > 0))
      {
         LastItem = CurItem;
         CurItem = CurItem->Next;
         pos--;
         npos++;
      }
   }

   if(CurItem)
   {
      if(LastItem)
      {
         /* insert the item before CurItem */
         MenuItem->Next = LastItem->Next;
         LastItem->Next = MenuItem;
      }
      else
      {
         /* insert at the beginning */
         Menu->MenuItemList = MenuItem;
         MenuItem->Next = CurItem;
      }
   }
   else
   {
      if(LastItem)
      {
         /* append item */
         LastItem->Next = MenuItem;
         MenuItem->Next = NULL;
      }
      else
      {
         /* insert first item */
         Menu->MenuItemList = MenuItem;
         MenuItem->Next = NULL;
      }
   }
   Menu->MenuInfo.MenuItemCount++;

   return npos;
}

BOOL FASTCALL
IntGetMenuItemInfo(PMENU_OBJECT Menu, /* UNUSED PARAM!! */
                   PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
{
   NTSTATUS Status;

   if(lpmii->fMask & (MIIM_FTYPE | MIIM_TYPE))
   {
      lpmii->fType = MenuItem->fType;
   }
   if(lpmii->fMask & MIIM_BITMAP)
   {
      lpmii->hbmpItem = MenuItem->hbmpItem;
   }
   if(lpmii->fMask & MIIM_CHECKMARKS)
   {
      lpmii->hbmpChecked = MenuItem->hbmpChecked;
      lpmii->hbmpUnchecked = MenuItem->hbmpUnchecked;
   }
   if(lpmii->fMask & MIIM_DATA)
   {
      lpmii->dwItemData = MenuItem->dwItemData;
   }
   if(lpmii->fMask & MIIM_ID)
   {
      lpmii->wID = MenuItem->wID;
   }
   if(lpmii->fMask & MIIM_STATE)
   {
      lpmii->fState = MenuItem->fState;
   }
   if(lpmii->fMask & MIIM_SUBMENU)
   {
      lpmii->hSubMenu = MenuItem->hSubMenu;
   }

   if ((lpmii->fMask & MIIM_STRING) ||
      ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
   {
      if (lpmii->dwTypeData == NULL)
      {
         lpmii->cch = MenuItem->Text.Length / sizeof(WCHAR);
      }
      else
      {
         Status = MmCopyToCaller(lpmii->dwTypeData, MenuItem->Text.Buffer,
                                 min(lpmii->cch * sizeof(WCHAR),
                                     MenuItem->Text.MaximumLength));
         if (! NT_SUCCESS(Status))
         {
            SetLastNtError(Status);
            return FALSE;
         }
      }
   }

   if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
   {
      lpmii->Rect = MenuItem->Rect;
      lpmii->XTab = MenuItem->XTab;
      lpmii->Text = MenuItem->Text.Buffer;
   }

   return TRUE;
}

BOOL FASTCALL
IntSetMenuItemInfo(PMENU_OBJECT MenuObject, PMENU_ITEM MenuItem, PROSMENUITEMINFO lpmii)
{
   PMENU_OBJECT SubMenuObject;
   UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR | MF_POPUP);

   if(!MenuItem || !MenuObject || !lpmii)
   {
      return FALSE;
   }
   if( lpmii->fType & ~fTypeMask)
   {
     DbgPrint("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask);
     lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE);
   }
   if(lpmii->fMask &  MIIM_TYPE)
   {
      if(lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP))
      {
         DbgPrint("IntSetMenuItemInfo: Invalid combination of fMask bits used\n");
         /* this does not happen on Win9x/ME */
         SetLastNtError( ERROR_INVALID_PARAMETER);
         return FALSE;
      }
      /*
       * Delete the menu item type when changing type from
       * MF_STRING.
       */
      if (MenuItem->fType != lpmii->fType &&
            MENU_ITEM_TYPE(MenuItem->fType) == MFT_STRING)
      {
         FreeMenuText(MenuItem);
         RtlInitUnicodeString(&MenuItem->Text, NULL);
      }
      if(lpmii->fType & MFT_BITMAP)
      {
         if(lpmii->hbmpItem)
           MenuItem->hbmpItem = lpmii->hbmpItem;
         else
         { /* Win 9x/Me stuff */
           MenuItem->hbmpItem = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
         }
      }
      MenuItem->fType |= lpmii->fType;
   }
   if (lpmii->fMask & MIIM_FTYPE )
   {
      if(( lpmii->fType & MFT_BITMAP))
      {
         DbgPrint("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
         SetLastNtError( ERROR_INVALID_PARAMETER);
         return FALSE;
      }
      MenuItem->fType |= lpmii->fType; /* Need to save all the flags, this fixed MFT_RIGHTJUSTIFY */
   }
   if(lpmii->fMask & MIIM_BITMAP)
   {
         MenuItem->hbmpItem = lpmii->hbmpItem;
   }
   if(lpmii->fMask & MIIM_CHECKMARKS)
   {
      MenuItem->hbmpChecked = lpmii->hbmpChecked;
      MenuItem->hbmpUnchecked = lpmii->hbmpUnchecked;
   }
   if(lpmii->fMask & MIIM_DATA)
   {
      MenuItem->dwItemData = lpmii->dwItemData;
   }
   if(lpmii->fMask & MIIM_ID)
   {
      MenuItem->wID = lpmii->wID;
   }
   if(lpmii->fMask & MIIM_STATE)
   {
      /* remove MFS_DEFAULT flag from all other menu items if this item
         has the MFS_DEFAULT state */
      if(lpmii->fState & MFS_DEFAULT)
         UserSetMenuDefaultItem(MenuObject, -1, 0);
      /* update the menu item state flags */
      UpdateMenuItemState(MenuItem->fState, lpmii->fState);
   }

   if(lpmii->fMask & MIIM_SUBMENU)
   {
      MenuItem->hSubMenu = lpmii->hSubMenu;
      /* Make sure the submenu is marked as a popup menu */
      if (MenuItem->hSubMenu)
      {
         SubMenuObject = UserGetMenuObject(MenuItem->hSubMenu);
         if (SubMenuObject != NULL)
         {
            SubMenuObject->MenuInfo.Flags |= MF_POPUP;
            MenuItem->fType |= MF_POPUP;
         }
         else
         {
            MenuItem->fType &= ~MF_POPUP;
         }
      }
      else
      {
         MenuItem->fType &= ~MF_POPUP;
      }
   }

   if ((lpmii->fMask & MIIM_STRING) ||
      ((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
   {
      FreeMenuText(MenuItem);

      if(lpmii->dwTypeData && lpmii->cch)
      {
         UNICODE_STRING Source;

         Source.Length =
            Source.MaximumLength = lpmii->cch * sizeof(WCHAR);
         Source.Buffer = lpmii->dwTypeData;

         MenuItem->Text.Buffer = (PWSTR)ExAllocatePoolWithTag(
                                    PagedPool, Source.Length + sizeof(WCHAR), TAG_STRING);
         if(MenuItem->Text.Buffer != NULL)
         {
            MenuItem->Text.Length = 0;
            MenuItem->Text.MaximumLength = Source.Length + sizeof(WCHAR);
            RtlCopyUnicodeString(&MenuItem->Text, &Source);
            MenuItem->Text.Buffer[MenuItem->Text.Length / sizeof(WCHAR)] = 0;
         }
         else
         {
            RtlInitUnicodeString(&MenuItem->Text, NULL);
         }
      }
      else
      {
         if (0 == (MenuObject->MenuInfo.Flags & MF_SYSMENU))
         {
            MenuItem->fType |= MF_SEPARATOR;
         }
         RtlInitUnicodeString(&MenuItem->Text, NULL);
      }
   }

   if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
   {
      MenuItem->Rect = lpmii->Rect;
      MenuItem->XTab = lpmii->XTab;
      lpmii->Text = MenuItem->Text.Buffer; /* Send back new allocated string or zero */
   }

   return TRUE;
}

BOOL FASTCALL
IntInsertMenuItem(PMENU_OBJECT MenuObject, UINT uItem, BOOL fByPosition,
                  PROSMENUITEMINFO ItemInfo)
{
   int pos = (int)uItem;
   PMENU_ITEM MenuItem;

   if (MAX_MENU_ITEMS <= MenuObject->MenuInfo.MenuItemCount)
   {
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return FALSE;
   }

   if (fByPosition)
   {
      /* calculate position */
      if(MenuObject->MenuInfo.MenuItemCount < pos)
      {
         pos = MenuObject->MenuInfo.MenuItemCount;
      }
   }
   else
   {
      pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, NULL, NULL);
   }
   if (pos < -1)
   {
      pos = -1;
   }

   MenuItem = ExAllocatePoolWithTag(PagedPool, sizeof(MENU_ITEM), TAG_MENUITEM);
   if (NULL == MenuItem)
   {
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return FALSE;
   }

   MenuItem->fType = MFT_STRING;
   MenuItem->fState = MFS_ENABLED | MFS_UNCHECKED;
   MenuItem->wID = 0;
   MenuItem->hSubMenu = (HMENU)0;
   MenuItem->hbmpChecked = (HBITMAP)0;
   MenuItem->hbmpUnchecked = (HBITMAP)0;
   MenuItem->dwItemData = 0;
   RtlInitUnicodeString(&MenuItem->Text, NULL);
   MenuItem->hbmpItem = (HBITMAP)0;

   if (! IntSetMenuItemInfo(MenuObject, MenuItem, ItemInfo))
   {
      ExFreePool(MenuItem);
      return FALSE;
   }

   /* Force size recalculation! */
   MenuObject->MenuInfo.Height = 0;

   pos = IntInsertMenuItemToList(MenuObject, MenuItem, pos);

   DPRINT("IntInsertMenuItemToList = %i\n", pos);

   return (pos >= 0);
}

UINT FASTCALL
IntEnableMenuItem(PMENU_OBJECT MenuObject, UINT uIDEnableItem, UINT uEnable)
{
   PMENU_ITEM MenuItem;
   UINT res = IntGetMenuItemByFlag(MenuObject, uIDEnableItem, uEnable, &MenuItem, NULL);
   if(!MenuItem || (res == (UINT)-1))
   {
      return (UINT)-1;
   }

   res = MenuItem->fState & (MF_GRAYED | MF_DISABLED);

   if(uEnable & MF_DISABLED)
   {
      if(!(MenuItem->fState & MF_DISABLED))
         MenuItem->fState |= MF_DISABLED;
      if(uEnable & MF_GRAYED)
      {
         if(!(MenuItem->fState & MF_GRAYED))
            MenuItem->fState |= MF_GRAYED;
      }
   }
   else
   {
      if(uEnable & MF_GRAYED)
      {
         if(!(MenuItem->fState & MF_GRAYED))
            MenuItem->fState |= MF_GRAYED;
         if(!(MenuItem->fState & MF_DISABLED))
            MenuItem->fState |= MF_DISABLED;
      }
      else
      {
         if(MenuItem->fState & MF_DISABLED)
            MenuItem->fState ^= MF_DISABLED;
         if(MenuItem->fState & MF_GRAYED)
            MenuItem->fState ^= MF_GRAYED;
      }
   }

   return res;
}


DWORD FASTCALL
IntBuildMenuItemList(PMENU_OBJECT MenuObject, PVOID Buffer, ULONG nMax)
{
   DWORD res = 0;
   UINT sz;
   ROSMENUITEMINFO mii;
   PVOID Buf;
   PMENU_ITEM CurItem = MenuObject->MenuItemList;
   PWCHAR StrOut;
   NTSTATUS Status;
   WCHAR NulByte;

   if (0 != nMax)
   {
      if (nMax < MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO))
      {
         return 0;
      }
      StrOut = (PWCHAR)((char *) Buffer + MenuObject->MenuInfo.MenuItemCount
                        * sizeof(ROSMENUITEMINFO));
      nMax -= MenuObject->MenuInfo.MenuItemCount * sizeof(ROSMENUITEMINFO);
      sz = sizeof(ROSMENUITEMINFO);
      Buf = Buffer;
      mii.cbSize = sizeof(ROSMENUITEMINFO);
      mii.fMask = 0;
      NulByte = L'\0';

      while (NULL != CurItem)
      {
         mii.cch = CurItem->Text.Length / sizeof(WCHAR);
         mii.dwItemData = CurItem->dwItemData;
         if (0 != CurItem->Text.Length)
         {
            mii.dwTypeData = StrOut;
         }
         else
         {
            mii.dwTypeData = NULL;
         }
         mii.fState = CurItem->fState;
         mii.fType = CurItem->fType;
         mii.hbmpChecked = CurItem->hbmpChecked;
         mii.hbmpItem = CurItem->hbmpItem;
         mii.hbmpUnchecked = CurItem->hbmpUnchecked;
         mii.hSubMenu = CurItem->hSubMenu;
         mii.Rect = CurItem->Rect;
         mii.XTab = CurItem->XTab;
         mii.Text = CurItem->Text.Buffer;

         Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
         if (! NT_SUCCESS(Status))
         {
            SetLastNtError(Status);
            return 0;
         }
         Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));

         if (0 != CurItem->Text.Length
               && (nMax >= CurItem->Text.Length + sizeof(WCHAR)))
         {
            /* copy string */
            Status = MmCopyToCaller(StrOut, CurItem->Text.Buffer,
                                    CurItem->Text.Length);
            if (! NT_SUCCESS(Status))
            {
               SetLastNtError(Status);
               return 0;
            }
            StrOut += CurItem->Text.Length / sizeof(WCHAR);
            Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
            if (! NT_SUCCESS(Status))
            {
               SetLastNtError(Status);
               return 0;
            }
            StrOut++;
            nMax -= CurItem->Text.Length + sizeof(WCHAR);
         }
         else if (0 != CurItem->Text.Length)
         {
            break;
         }

         CurItem = CurItem->Next;
         res++;
      }
   }
   else
   {
      while (NULL != CurItem)
      {
         res += sizeof(ROSMENUITEMINFO) + CurItem->Text.Length + sizeof(WCHAR);
         CurItem = CurItem->Next;
      }
   }

   return res;
}


DWORD FASTCALL
IntCheckMenuItem(PMENU_OBJECT MenuObject, UINT uIDCheckItem, UINT uCheck)
{
   PMENU_ITEM MenuItem;
   int res = -1;

   if((IntGetMenuItemByFlag(MenuObject, uIDCheckItem, uCheck, &MenuItem, NULL) < 0) || !MenuItem)
   {
      return -1;
   }

   res = (DWORD)(MenuItem->fState & MF_CHECKED);
   if(uCheck & MF_CHECKED)
   {
      if(!(MenuItem->fState & MF_CHECKED))
         MenuItem->fState |= MF_CHECKED;
   }
   else
   {
      if(MenuItem->fState & MF_CHECKED)
         MenuItem->fState ^= MF_CHECKED;
   }

   return (DWORD)res;
}

BOOL FASTCALL
IntHiliteMenuItem(PWINDOW_OBJECT WindowObject, PMENU_OBJECT MenuObject,
                  UINT uItemHilite, UINT uHilite)
{
   PMENU_ITEM MenuItem;
   BOOL res = IntGetMenuItemByFlag(MenuObject, uItemHilite, uHilite, &MenuItem, NULL);
   if(!MenuItem || !res)
   {
      return FALSE;
   }

   if(uHilite & MF_HILITE)
   {
      if(!(MenuItem->fState & MF_HILITE))
         MenuItem->fState |= MF_HILITE;
   }
   else
   {
      if(MenuItem->fState & MF_HILITE)
         MenuItem->fState ^= MF_HILITE;
   }

   /* FIXME - update the window's menu */

   return TRUE;
}

BOOL FASTCALL
UserSetMenuDefaultItem(PMENU_OBJECT MenuObject, UINT uItem, UINT fByPos)
{
   BOOL ret = FALSE;
   PMENU_ITEM MenuItem = MenuObject->MenuItemList;

   if(uItem == (UINT)-1)
   {
      while(MenuItem)
      {
         if(MenuItem->fState & MFS_DEFAULT)
            MenuItem->fState ^= MFS_DEFAULT;
         MenuItem = MenuItem->Next;
      }
      return TRUE;
   }

   if(fByPos)
   {
      UINT pos = 0;
      while(MenuItem)
      {
         if(pos == uItem)
         {
            if(!(MenuItem->fState & MFS_DEFAULT))
               MenuItem->fState |= MFS_DEFAULT;
            ret = TRUE;
         }
         else
         {
            if(MenuItem->fState & MFS_DEFAULT)
               MenuItem->fState ^= MFS_DEFAULT;
         }
         pos++;
         MenuItem = MenuItem->Next;
      }
   }
   else
   {
      while(MenuItem)
      {
         if(!ret && (MenuItem->wID == uItem))
         {
            if(!(MenuItem->fState & MFS_DEFAULT))
               MenuItem->fState |= MFS_DEFAULT;
            ret = TRUE;
         }
         else
         {
            if(MenuItem->fState & MFS_DEFAULT)
               MenuItem->fState ^= MFS_DEFAULT;
         }
         MenuItem = MenuItem->Next;
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -