PPH_EMENU_ITEM CreateSendToMenu( _In_ BOOLEAN ProcessesMenu, _In_ PPH_EMENU_ITEM Parent, _In_ PPH_STRING FileName ) { PPH_EMENU_ITEM sendToMenu; PPH_EMENU_ITEM menuItem; ULONG insertIndex; sendToMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"Sen&d to", NULL); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, MENUITEM_HYBRIDANALYSIS_UPLOAD, L"&hybrid-analysis.com", FileName), ULONG_MAX); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, MENUITEM_VIRUSTOTAL_UPLOAD, L"&virustotal.com", FileName), ULONG_MAX); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, MENUITEM_JOTTI_UPLOAD, L"virusscan.&jotti.org", FileName), ULONG_MAX); if (ProcessesMenu && (menuItem = PhFindEMenuItem(Parent, PH_EMENU_FIND_STARTSWITH, L"Search online", 0))) { insertIndex = PhIndexOfEMenuItem(Parent, menuItem); PhInsertEMenuItem(Parent, sendToMenu, insertIndex + 1); PhInsertEMenuItem(Parent, PhCreateEMenuSeparator(), insertIndex + 2); } else { PhInsertEMenuItem(Parent, PhCreateEMenuSeparator(), ULONG_MAX); PhInsertEMenuItem(Parent, sendToMenu, ULONG_MAX); } return sendToMenu; }
VOID NTAPI MainMenuInitializingCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_EMENU_ITEM systemMenu; PPH_EMENU_ITEM bootMenuItem; if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS) return; if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0))) { PhInsertEMenuItem(menuInfo->Menu, PhCreateEMenuSeparator(), -1); PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"&System", NULL), -1); } PhInsertEMenuItem(systemMenu, bootMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, BOOT_ENTRIES_MENUITEM, L"Firm&ware Table", NULL), -1); if (!PhGetOwnTokenAttributes().Elevated) { bootMenuItem->Flags |= PH_EMENU_DISABLED; } }
VOID NTAPI ThreadMenuInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_THREAD_ITEM threadItem; ULONG insertIndex; PPH_EMENU_ITEM menuItem; if (menuInfo->u.Thread.NumberOfThreads == 1) threadItem = menuInfo->u.Thread.Threads[0]; else threadItem = NULL; if (menuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Resume", 0)) insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1; else insertIndex = 0; PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_THREAD_CANCELIO, L"Cancel I/O", threadItem), insertIndex); if (!threadItem) menuItem->Flags |= PH_EMENU_DISABLED; }
PPH_EMENU_ITEM CreateSendToMenu( __in PPH_EMENU_ITEM Parent, __in PWSTR InsertAfter, __in PPH_STRING FileName ) { PPH_EMENU_ITEM sendToMenu; PPH_EMENU_ITEM menuItem; ULONG insertIndex; // Create the Send To menu. sendToMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"Send To", NULL); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_SENDTO_SERVICE1, L"virustotal.com", FileName), -1); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_SENDTO_SERVICE2, L"virusscan.jotti.org", FileName), -1); PhInsertEMenuItem(sendToMenu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_SENDTO_SERVICE3, L"camas.comodo.com", FileName), -1); menuItem = PhFindEMenuItem(Parent, PH_EMENU_FIND_STARTSWITH, InsertAfter, 0); if (menuItem) insertIndex = PhIndexOfEMenuItem(Parent, menuItem); else insertIndex = -1; PhInsertEMenuItem(Parent, sendToMenu, insertIndex + 1); return sendToMenu; }
VOID NTAPI ProcessMenuInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_PROCESS_ITEM processItem; ULONG flags; PPH_EMENU_ITEM miscMenu; if (menuInfo->u.Process.NumberOfProcesses == 1) processItem = menuInfo->u.Process.Processes[0]; else processItem = NULL; flags = 0; if (!processItem) flags = PH_EMENU_DISABLED; miscMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"Miscellaneous", 0); if (miscMenu) { PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_UNLOADEDMODULES, L"Unloaded Modules", processItem), -1); PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_WSWATCH, L"WS Watch", processItem), -1); } }
VOID NTAPI MainMenuInitializingCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { ULONG insertIndex; PPH_EMENU_ITEM menuItem; PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_VIEW) return; if (menuItem = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_STARTSWITH, L"System Information", 0)) insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1; else insertIndex = 0; PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_WINDOWS, L"Windows", NULL), insertIndex); if (PhGetIntegerSetting(SETTING_NAME_SHOW_DESKTOP_WINDOWS)) { insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1; PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_DESKTOPWINDOWS, L"Desktop Windows...", NULL), insertIndex); } }
VOID NTAPI MainMenuInitializingCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_EMENU_ITEM systemMenu; if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS) return; if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0))) { PhInsertEMenuItem(menuInfo->Menu, PhCreateEMenuSeparator(), -1); PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"&System", NULL), -1); } PhInsertEMenuItem(systemMenu, PhPluginCreateEMenuItem(PluginInstance, 0, DNSCACHE_MENUITEM, L"&DNS Cache Table", NULL), -1); }
VOID NTAPI ModuleMenuInitializingCallback( __in_opt PVOID Parameter, __in_opt PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_PROCESS_ITEM processItem; BOOLEAN addMenuItem; PPH_MODULE_ITEM moduleItem; ULONG insertIndex; PPH_EMENU_ITEM menuItem; addMenuItem = FALSE; if (processItem = PhReferenceProcessItem(menuInfo->u.Module.ProcessId)) { if (processItem->ServiceList && processItem->ServiceList->Count != 0) addMenuItem = TRUE; PhDereferenceObject(processItem); } if (!addMenuItem) return; if (menuInfo->u.Module.NumberOfModules == 1) moduleItem = menuInfo->u.Module.Modules[0]; else moduleItem = NULL; if (menuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Inspect", 0)) insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1; else insertIndex = 0; ModuleProcessId = menuInfo->u.Module.ProcessId; PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_MODULE_SERVICES, L"Services", moduleItem), insertIndex); if (!moduleItem) menuItem->Flags |= PH_EMENU_DISABLED; }
VOID NTAPI ProcessMenuInitializingCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter; PPH_EMENU_ITEM miscMenuItem; PPH_EMENU_ITEM criticalMenuItem; PPH_PROCESS_ITEM processItem; miscMenuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Miscellaneous", 0); if (!miscMenuItem) return; processItem = menuInfo->u.Process.NumberOfProcesses == 1 ? menuInfo->u.Process.Processes[0] : NULL; criticalMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, CRITICAL_MENU_ITEM, L"&Critical", processItem); PhInsertEMenuItem(miscMenuItem, criticalMenuItem, -1); if (processItem) { HANDLE processHandle; ULONG breakOnTermination; if (NT_SUCCESS(PhOpenProcess(&processHandle, PROCESS_QUERY_INFORMATION, processItem->ProcessId))) { if (NT_SUCCESS(NtQueryInformationProcess(processHandle, ProcessBreakOnTermination, &breakOnTermination, sizeof(ULONG), NULL))) { if (breakOnTermination) criticalMenuItem->Flags |= PH_EMENU_CHECKED; } NtClose(processHandle); } } else { criticalMenuItem->Flags |= PH_EMENU_DISABLED; } }
/** * Sets the flags of a menu item. * * \param Item The parent menu item. * \param Id The identifier of the child menu item. * \param Mask The flags to modify. * \param Value The new value of the flags. */ BOOLEAN PhSetFlagsEMenuItem( __in PPH_EMENU_ITEM Item, __in ULONG Id, __in ULONG Mask, __in ULONG Value ) { PPH_EMENU_ITEM item; item = PhFindEMenuItem(Item, PH_EMENU_FIND_DESCEND, NULL, Id); if (item) { item->Flags &= ~Mask; item->Flags |= Value; return TRUE; } else { return FALSE; } }
VOID NTAPI NetworkMenuInitializingCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PPH_PLUGIN_MENU_INFORMATION menuInfo = (PPH_PLUGIN_MENU_INFORMATION)Parameter; PPH_NETWORK_ITEM networkItem; PPH_EMENU_ITEM toolsMenu; PPH_EMENU_ITEM closeMenuItem; if (menuInfo->u.Network.NumberOfNetworkItems == 1) networkItem = menuInfo->u.Network.NetworkItems[0]; else networkItem = NULL; // Create the Tools menu. toolsMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"Tools", NULL); PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_PING, L"Ping", networkItem), -1); PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_TRACEROUTE, L"Traceroute", networkItem), -1); PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_WHOIS, L"Whois", networkItem), -1); PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_PATHPING, L"PathPing", networkItem), -1); // Insert the Tools menu into the network menu. closeMenuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Close", 0); PhInsertEMenuItem(menuInfo->Menu, toolsMenu, closeMenuItem ? PhIndexOfEMenuItem(menuInfo->Menu, closeMenuItem) : 1); toolsMenu->Flags |= PH_EMENU_DISABLED; if (networkItem) { if (!PhIsNullIpAddress(&networkItem->RemoteEndpoint.Address)) { toolsMenu->Flags &= ~PH_EMENU_DISABLED; } } }
VOID PhpInitializeThreadMenu( _In_ PPH_EMENU Menu, _In_ HANDLE ProcessId, _In_ PPH_THREAD_ITEM *Threads, _In_ ULONG NumberOfThreads ) { PPH_EMENU_ITEM item; if (NumberOfThreads == 0) { PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED); } else if (NumberOfThreads == 1) { // All menu items are enabled by default. } else { ULONG menuItemsMultiEnabled[] = { ID_THREAD_TERMINATE, ID_THREAD_SUSPEND, ID_THREAD_RESUME, ID_THREAD_COPY }; ULONG i; PhSetFlagsAllEMenuItems(Menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED); // These menu items are capable of manipulating // multiple threads. for (i = 0; i < sizeof(menuItemsMultiEnabled) / sizeof(ULONG); i++) { PhEnableEMenuItem(Menu, menuItemsMultiEnabled[i], TRUE); } } // Remove irrelevant menu items. if (WindowsVersion < WINDOWS_VISTA) { // Remove I/O priority. if (item = PhFindEMenuItem(Menu, 0, L"I/O Priority", 0)) PhDestroyEMenuItem(item); // Remove page priority. if (item = PhFindEMenuItem(Menu, 0, L"Page Priority", 0)) PhDestroyEMenuItem(item); } PhEnableEMenuItem(Menu, ID_THREAD_TOKEN, FALSE); // Priority if (NumberOfThreads == 1) { HANDLE threadHandle; ULONG threadPriority = THREAD_PRIORITY_ERROR_RETURN; IO_PRIORITY_HINT ioPriority = -1; ULONG pagePriority = -1; ULONG id = 0; if (NT_SUCCESS(PhOpenThread( &threadHandle, ThreadQueryAccess, Threads[0]->ThreadId ))) { THREAD_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(PhGetThreadBasicInformation(threadHandle, &basicInfo))) { threadPriority = basicInfo.BasePriority; } if (WindowsVersion >= WINDOWS_VISTA) { PhGetThreadIoPriority(threadHandle, &ioPriority); PhGetThreadPagePriority(threadHandle, &pagePriority); } // Token { HANDLE tokenHandle; if (NT_SUCCESS(NtOpenThreadToken( threadHandle, TOKEN_QUERY, TRUE, &tokenHandle ))) { PhEnableEMenuItem(Menu, ID_THREAD_TOKEN, TRUE); NtClose(tokenHandle); } } NtClose(threadHandle); } switch (threadPriority) { case THREAD_PRIORITY_TIME_CRITICAL + 1: case THREAD_PRIORITY_TIME_CRITICAL: id = ID_PRIORITY_TIMECRITICAL; break; case THREAD_PRIORITY_HIGHEST: id = ID_PRIORITY_HIGHEST; break; case THREAD_PRIORITY_ABOVE_NORMAL: id = ID_PRIORITY_ABOVENORMAL; break; case THREAD_PRIORITY_NORMAL: id = ID_PRIORITY_NORMAL; break; case THREAD_PRIORITY_BELOW_NORMAL: id = ID_PRIORITY_BELOWNORMAL; break; case THREAD_PRIORITY_LOWEST: id = ID_PRIORITY_LOWEST; break; case THREAD_PRIORITY_IDLE: case THREAD_PRIORITY_IDLE - 1: id = ID_PRIORITY_IDLE; break; } if (id != 0) { PhSetFlagsEMenuItem(Menu, id, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK); } if (ioPriority != -1) { id = 0; switch (ioPriority) { case IoPriorityVeryLow: id = ID_IOPRIORITY_VERYLOW; break; case IoPriorityLow: id = ID_IOPRIORITY_LOW; break; case IoPriorityNormal: id = ID_IOPRIORITY_NORMAL; break; case IoPriorityHigh: id = ID_IOPRIORITY_HIGH; break; } if (id != 0) { PhSetFlagsEMenuItem(Menu, id, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK); } } if (pagePriority != -1) { id = 0; switch (pagePriority) { case MEMORY_PRIORITY_VERY_LOW: id = ID_PAGEPRIORITY_VERYLOW; break; case MEMORY_PRIORITY_LOW: id = ID_PAGEPRIORITY_LOW; break; case MEMORY_PRIORITY_MEDIUM: id = ID_PAGEPRIORITY_MEDIUM; break; case MEMORY_PRIORITY_BELOW_NORMAL: id = ID_PAGEPRIORITY_BELOWNORMAL; break; case MEMORY_PRIORITY_NORMAL: id = ID_PAGEPRIORITY_NORMAL; break; } if (id != 0) { PhSetFlagsEMenuItem(Menu, id, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK); } } } }
/** * Finds a child menu item. * * \param Item The parent menu item. * \param Flags A combination of the following: * \li \c PH_EMENU_FIND_DESCEND Searches recursively within child * menu items. * \li \c PH_EMENU_FIND_STARTSWITH Performs a partial text search * instead of an exact search. * \li \c PH_EMENU_FIND_LITERAL Performs a literal search instead of * ignoring prefix characters (ampersands). * \param Text The text of the menu item to find. If NULL, the text * is ignored. * \param Id The identifier of the menu item to find. If 0, the * identifier is ignored. * * \return The found menu item, or NULL if the menu item could not * be found. */ PPH_EMENU_ITEM PhFindEMenuItem( __in PPH_EMENU_ITEM Item, __in ULONG Flags, __in_opt PWSTR Text, __in_opt ULONG Id ) { ULONG i; PH_STRINGREF searchText; if (!Item->Items) return NULL; if (Text && (Flags & PH_EMENU_FIND_LITERAL)) PhInitializeStringRef(&searchText, Text); for (i = 0; i < Item->Items->Count; i++) { PPH_EMENU_ITEM item; item = Item->Items->Items[i]; if (Text) { if (Flags & PH_EMENU_FIND_LITERAL) { PH_STRINGREF text; PhInitializeStringRef(&text, item->Text); if (Flags & PH_EMENU_FIND_STARTSWITH) { if (PhStartsWithStringRef(&text, &searchText, TRUE)) return item; } else { if (PhEqualStringRef(&text, &searchText, TRUE)) return item; } } else { if (PhCompareUnicodeStringZIgnoreMenuPrefix(Text, item->Text, TRUE, !!(Flags & PH_EMENU_FIND_STARTSWITH)) == 0) return item; } } if (Id && item->Id == Id) return item; if (Flags & PH_EMENU_FIND_DESCEND) { PPH_EMENU_ITEM foundItem; foundItem = PhFindEMenuItem(item, Flags, Text, Id); if (foundItem) return foundItem; } } return NULL; }