VOID PhPluginsInitialization( VOID ) { ULONG i; for (i = 0; i < GeneralCallbackMaximum; i++) PhInitializeCallback(&GeneralCallbacks[i]); if (WindowsVersion <= WINDOWS_XP) { PH_STRINGREF extendedTools = PH_STRINGREF_INIT(L"ExtendedTools.dll"); // HACK and violation of abstraction. // Always disable ExtendedTools on XP to avoid the annoying error message. PhSetPluginDisabled(&extendedTools, TRUE); } }
VOID PhpHandlePluginLoadError( _In_ PPH_STRING FileName, _In_opt_ PPH_STRING ErrorMessage ) { PPH_STRING baseName; baseName = PhGetBaseName(FileName); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, L"Unable to load %s: %s\nDo you want to disable the plugin?", baseName->Buffer, PhGetStringOrDefault(ErrorMessage, L"An unknown error occurred.") ) == IDYES) { PhSetPluginDisabled(&baseName->sr, TRUE); } PhDereferenceObject(baseName); }
INT_PTR CALLBACK PhpPluginsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PPH_AVL_LINKS links; PhCenterWindow(hwndDlg, PhMainWndHandle); PluginsLv = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(PluginsLv, FALSE, TRUE); PhSetControlTheme(PluginsLv, L"explorer"); PhAddListViewColumn(PluginsLv, 0, 0, 0, LVCFMT_LEFT, 280, L"Name"); PhAddListViewColumn(PluginsLv, 1, 1, 1, LVCFMT_LEFT, 100, L"Author"); PhSetExtendedListView(PluginsLv); ExtendedListView_SetItemColorFunction(PluginsLv, PhpPluginColorFunction); DisabledPluginLookup = PhCreateSimpleHashtable(10); for (links = PhMinimumElementAvlTree(&PhPluginsByName); links; links = PhSuccessorElementAvlTree(links)) { PPH_PLUGIN plugin = CONTAINING_RECORD(links, PH_PLUGIN, Links); INT lvItemIndex; PH_STRINGREF baseNameSr; lvItemIndex = PhAddListViewItem(PluginsLv, MAXINT, plugin->Information.DisplayName ? plugin->Information.DisplayName : plugin->Name.Buffer, plugin); if (plugin->Information.Author) PhSetListViewSubItem(PluginsLv, lvItemIndex, 1, plugin->Information.Author); PhInitializeStringRefLongHint(&baseNameSr, PhpGetPluginBaseName(plugin)); if (PhIsPluginDisabled(&baseNameSr)) PhAddItemSimpleHashtable(DisabledPluginLookup, plugin, NULL); } DisabledPluginInstances = PhCreateList(10); PhpAddDisabledPlugins(); ExtendedListView_SortItems(PluginsLv); SelectedPlugin = NULL; PhpRefreshPluginDetails(hwndDlg); } break; case WM_DESTROY: { ULONG i; for (i = 0; i < DisabledPluginInstances->Count; i++) PhpFreeDisabledPlugin(DisabledPluginInstances->Items[i]); PhDereferenceObject(DisabledPluginInstances); PhDereferenceObject(DisabledPluginLookup); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; case IDC_DISABLE: { if (SelectedPlugin) { PWSTR baseName; PH_STRINGREF baseNameRef; BOOLEAN newDisabledState; baseName = PhpGetPluginBaseName(SelectedPlugin); PhInitializeStringRef(&baseNameRef, baseName); newDisabledState = !PhIsPluginDisabled(&baseNameRef); PhSetPluginDisabled(&baseNameRef, newDisabledState); PhpUpdateDisabledPlugin(hwndDlg, PhFindListViewItemByFlags(PluginsLv, -1, LVNI_SELECTED), SelectedPlugin, newDisabledState); SetDlgItemText(hwndDlg, IDC_DISABLE, PhpGetPluginDisableButtonText(baseName)); } } break; case IDC_OPTIONS: { if (SelectedPlugin && IS_PLUGIN_LOADED(SelectedPlugin)) { PhInvokeCallback(PhGetPluginCallback(SelectedPlugin, PluginCallbackShowOptions), hwndDlg); } } break; case IDC_CLEANUP: { if (PhShowMessage(hwndDlg, MB_ICONQUESTION | MB_YESNO, L"Do you want to clean up unused plugin settings?") == IDYES) { PhClearIgnoredSettings(); } } break; case IDC_OPENURL: { NOTHING; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case LVN_ITEMCHANGED: { if (header->hwndFrom == PluginsLv) { if (ListView_GetSelectedCount(PluginsLv) == 1) SelectedPlugin = PhGetSelectedListViewItemParam(PluginsLv); else SelectedPlugin = NULL; PhpRefreshPluginDetails(hwndDlg); } } break; case NM_CLICK: { if (header->hwndFrom == GetDlgItem(hwndDlg, IDC_OPENURL)) { if (SelectedPlugin && IS_PLUGIN_LOADED(SelectedPlugin)) PhShellExecute(hwndDlg, SelectedPlugin->Information.Url, NULL); } } break; case NM_DBLCLK: { if (header->hwndFrom == PluginsLv) { if (SelectedPlugin && IS_PLUGIN_LOADED(SelectedPlugin)) { PhInvokeCallback(PhGetPluginCallback(SelectedPlugin, PluginCallbackShowOptions), hwndDlg); } } } break; } } break; } REFLECT_MESSAGE_DLG(hwndDlg, PluginsLv, uMsg, wParam, lParam); return FALSE; }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // Handle load errors. // In certain startup modes we want to ignore all plugin load errors. if (LoadErrors && LoadErrors->Count != 0 && !PhStartupParameters.PhSvc) { PH_STRING_BUILDER sb; ULONG i; PPHP_PLUGIN_LOAD_ERROR loadError; PPH_STRING baseName; PhInitializeStringBuilder(&sb, 100); PhAppendStringBuilder2(&sb, L"Unable to load the following plugin(s):\n\n"); for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhAppendFormatStringBuilder(&sb, L"%s: %s\n", baseName->Buffer, PhGetStringOrDefault(loadError->ErrorMessage, L"An unknown error occurred.")); PhDereferenceObject(baseName); } PhAppendStringBuilder2(&sb, L"\nDo you want to disable the above plugin(s)?"); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, sb.String->Buffer ) == IDYES) { ULONG i; for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhSetPluginDisabled(&baseName->sr, TRUE); PhDereferenceObject(baseName); } } PhDeleteStringBuilder(&sb); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad, TRUE); }