mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
* got rid of SHGetFileInfo usage - vastly improves startup time and memory usage
* cache PhGetSystemDirectory() string git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3716 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -2,6 +2,7 @@ Process Hacker
|
||||
|
||||
2.7
|
||||
* NEW/IMPROVED:
|
||||
* Vastly improved startup time, and lower memory usage
|
||||
* FIXED:
|
||||
* ToolStatus layout problems
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <circbuf.h>
|
||||
#include <phnet.h>
|
||||
#include <providers.h>
|
||||
#include "resource.h"
|
||||
#include "../resource.h"
|
||||
|
||||
#define KPH_ERROR_MESSAGE (L"KProcessHacker does not support your operating system " \
|
||||
L"or could not be loaded. Make sure Process Hacker is running " \
|
||||
@@ -267,8 +267,6 @@ VOID PhUpdateProcessNode(
|
||||
|
||||
VOID PhTickProcessNodes();
|
||||
|
||||
HICON PhGetStockAppIcon();
|
||||
|
||||
PHAPPAPI
|
||||
PPH_PROCESS_ITEM PhGetSelectedProcessItem();
|
||||
|
||||
|
||||
@@ -33,10 +33,6 @@
|
||||
#include <iphlpapi.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
typedef BOOL (WINAPI *_FileIconInit)(
|
||||
__in BOOL RestoreCache
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *_LoadIconMetric)(
|
||||
__in HINSTANCE hinst,
|
||||
__in PCWSTR pszName,
|
||||
@@ -272,22 +268,6 @@ BOOLEAN PhMainWndInitialization(
|
||||
{
|
||||
PH_RECTANGLE windowRectangle;
|
||||
|
||||
// Initialize the system image lists.
|
||||
{
|
||||
HMODULE shell32;
|
||||
_FileIconInit fileIconInit;
|
||||
|
||||
shell32 = LoadLibrary(L"shell32.dll");
|
||||
|
||||
if (shell32)
|
||||
{
|
||||
fileIconInit = (_FileIconInit)GetProcAddress(shell32, (PSTR)660);
|
||||
|
||||
if (fileIconInit)
|
||||
fileIconInit(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (PhGetIntegerSetting(L"FirstRun"))
|
||||
{
|
||||
PPH_STRING autoDbghelpPath;
|
||||
@@ -2495,9 +2475,23 @@ VOID PhpAddIconProcesses(
|
||||
|
||||
// Menu icons only work properly on Vista and above.
|
||||
if (WindowsVersion >= WINDOWS_VISTA)
|
||||
iconBitmap = PhIconToBitmap(processItem->SmallIcon ? processItem->SmallIcon : PhGetStockAppIcon(), 16, 16);
|
||||
{
|
||||
if (processItem->SmallIcon)
|
||||
{
|
||||
iconBitmap = PhIconToBitmap(processItem->SmallIcon, 16, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
HICON icon;
|
||||
|
||||
PhGetStockApplicationIcon(&icon, NULL);
|
||||
iconBitmap = PhIconToBitmap(icon, 16, 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iconBitmap = NULL;
|
||||
}
|
||||
|
||||
subMenu->Bitmap = iconBitmap;
|
||||
Bitmaps[i] = iconBitmap;
|
||||
@@ -4321,8 +4315,11 @@ VOID PhMainWndOnNetworkItemAdded(
|
||||
|
||||
if (!NetworkImageListWrapper.Handle)
|
||||
{
|
||||
HICON icon;
|
||||
|
||||
PhGetStockApplicationIcon(&icon, NULL);
|
||||
PhInitializeImageListWrapper(&NetworkImageListWrapper, 16, 16, ILC_COLOR32 | ILC_MASK);
|
||||
PhImageListWrapperAddIcon(&NetworkImageListWrapper, PhGetStockAppIcon());
|
||||
PhImageListWrapperAddIcon(&NetworkImageListWrapper, icon);
|
||||
ListView_SetImageList(NetworkListViewHandle, NetworkImageListWrapper.Handle, LVSIL_SMALL);
|
||||
}
|
||||
|
||||
|
||||
@@ -582,26 +582,16 @@ VOID PhpProcessQueryStage1(
|
||||
if (processItem->FileName)
|
||||
{
|
||||
// Small icon, large icon.
|
||||
if (ExtractIconEx(
|
||||
processItem->FileName->Buffer,
|
||||
0,
|
||||
&Data->LargeIcon,
|
||||
&Data->SmallIcon,
|
||||
1
|
||||
) == 0)
|
||||
{
|
||||
SHFILEINFO fileInfo;
|
||||
|
||||
if (SHGetFileInfo(
|
||||
processItem->FileName->Buffer,
|
||||
0,
|
||||
&fileInfo,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | SHGFI_SMALLICON
|
||||
))
|
||||
Data->SmallIcon = fileInfo.hIcon;
|
||||
|
||||
if (SHGetFileInfo(
|
||||
processItem->FileName->Buffer,
|
||||
0,
|
||||
&fileInfo,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | SHGFI_LARGEICON
|
||||
))
|
||||
Data->LargeIcon = fileInfo.hIcon;
|
||||
Data->LargeIcon = NULL;
|
||||
Data->SmallIcon = NULL;
|
||||
}
|
||||
|
||||
// Version info.
|
||||
@@ -610,30 +600,22 @@ VOID PhpProcessQueryStage1(
|
||||
|
||||
// Use the default EXE icon if we didn't get the file's icon.
|
||||
{
|
||||
SHFILEINFO fileInfo;
|
||||
|
||||
if (!Data->SmallIcon)
|
||||
if (!Data->SmallIcon || !Data->LargeIcon)
|
||||
{
|
||||
if (SHGetFileInfo(
|
||||
L".exe",
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
&fileInfo,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES
|
||||
))
|
||||
Data->SmallIcon = fileInfo.hIcon;
|
||||
}
|
||||
if (Data->SmallIcon)
|
||||
{
|
||||
DestroyIcon(Data->SmallIcon);
|
||||
Data->SmallIcon = NULL;
|
||||
}
|
||||
else if (Data->LargeIcon)
|
||||
{
|
||||
DestroyIcon(Data->LargeIcon);
|
||||
Data->LargeIcon = NULL;
|
||||
}
|
||||
|
||||
if (!Data->LargeIcon)
|
||||
{
|
||||
if (SHGetFileInfo(
|
||||
L".exe",
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
&fileInfo,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES
|
||||
))
|
||||
Data->LargeIcon = fileInfo.hIcon;
|
||||
PhGetStockApplicationIcon(&Data->SmallIcon, &Data->LargeIcon);
|
||||
Data->SmallIcon = DuplicateIcon(NULL, Data->SmallIcon);
|
||||
Data->LargeIcon = DuplicateIcon(NULL, Data->LargeIcon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -463,25 +463,6 @@ VOID PhTickProcessNodes()
|
||||
}
|
||||
}
|
||||
|
||||
HICON PhGetStockAppIcon()
|
||||
{
|
||||
if (!StockAppIcon)
|
||||
{
|
||||
SHFILEINFO fileInfo = { 0 };
|
||||
|
||||
SHGetFileInfo(
|
||||
L".exe",
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
&fileInfo,
|
||||
sizeof(SHFILEINFO),
|
||||
SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON
|
||||
);
|
||||
StockAppIcon = fileInfo.hIcon;
|
||||
}
|
||||
|
||||
return StockAppIcon;
|
||||
}
|
||||
|
||||
VOID PhpUpdateProcessNodeWsCounters(
|
||||
__inout PPH_PROCESS_NODE ProcessNode
|
||||
)
|
||||
@@ -1480,7 +1461,7 @@ BOOLEAN NTAPI PhpProcessTreeListCallback(
|
||||
}
|
||||
else
|
||||
{
|
||||
getNodeIcon->Icon = PhGetStockAppIcon();
|
||||
PhGetStockApplicationIcon(&getNodeIcon->Icon, NULL);
|
||||
}
|
||||
|
||||
getNodeIcon->Flags = TLC_CACHE;
|
||||
|
||||
@@ -774,6 +774,65 @@ VOID PhImageListWrapperRemove(
|
||||
PhAddItemList(Wrapper->FreeList, (PVOID)Index);
|
||||
}
|
||||
|
||||
VOID PhGetStockApplicationIcon(
|
||||
__out_opt HICON *SmallIcon,
|
||||
__out_opt HICON *LargeIcon
|
||||
)
|
||||
{
|
||||
static PH_INITONCE initOnce = PH_INITONCE_INIT;
|
||||
static HICON smallIcon = NULL;
|
||||
static HICON largeIcon = NULL;
|
||||
|
||||
// This no longer uses SHGetFileInfo because it is *very* slow and causes
|
||||
// many other DLLs to be loaded, increasing memory usage.
|
||||
|
||||
if (PhBeginInitOnce(&initOnce))
|
||||
{
|
||||
PPH_STRING systemDirectory;
|
||||
PPH_STRING dllFileName;
|
||||
|
||||
// user32,0 (Vista and above) or shell32,2 (XP) contains the default application icon.
|
||||
|
||||
if (systemDirectory = PhGetSystemDirectory())
|
||||
{
|
||||
PH_STRINGREF dllBaseName;
|
||||
ULONG index;
|
||||
|
||||
// TODO: Find a better solution.
|
||||
|
||||
if (WindowsVersion >= WINDOWS_VISTA)
|
||||
{
|
||||
PhInitializeStringRef(&dllBaseName, L"\\user32.dll");
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PhInitializeStringRef(&dllBaseName, L"\\shell32.dll");
|
||||
index = 2;
|
||||
}
|
||||
|
||||
dllFileName = PhConcatStringRef2(&systemDirectory->sr, &dllBaseName);
|
||||
PhDereferenceObject(systemDirectory);
|
||||
|
||||
ExtractIconEx(dllFileName->Buffer, index, &largeIcon, &smallIcon, 1);
|
||||
PhDereferenceObject(dllFileName);
|
||||
}
|
||||
|
||||
// Fallback icons - this is bad, because the icon isn't scaled correctly.
|
||||
if (!smallIcon)
|
||||
smallIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
if (!largeIcon)
|
||||
largeIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
|
||||
PhEndInitOnce(&initOnce);
|
||||
}
|
||||
|
||||
if (SmallIcon)
|
||||
*SmallIcon = smallIcon;
|
||||
if (LargeIcon)
|
||||
*LargeIcon = largeIcon;
|
||||
}
|
||||
|
||||
HICON PhGetFileShellIcon(
|
||||
__in_opt PWSTR FileName,
|
||||
__in_opt PWSTR DefaultExtension,
|
||||
@@ -784,6 +843,34 @@ HICON PhGetFileShellIcon(
|
||||
ULONG iconFlag;
|
||||
HICON icon;
|
||||
|
||||
if (DefaultExtension && PhEqualStringZ(DefaultExtension, L".exe", TRUE))
|
||||
{
|
||||
// Special case for executable files (see above for reasoning).
|
||||
|
||||
icon = NULL;
|
||||
|
||||
if (FileName)
|
||||
{
|
||||
ExtractIconEx(
|
||||
FileName,
|
||||
0,
|
||||
LargeIcon ? &icon : NULL,
|
||||
!LargeIcon ? &icon : NULL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
if (!icon)
|
||||
{
|
||||
PhGetStockApplicationIcon(
|
||||
!LargeIcon ? &icon : NULL,
|
||||
LargeIcon ? &icon : NULL
|
||||
);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
iconFlag = LargeIcon ? SHGFI_LARGEICON : SHGFI_SMALLICON;
|
||||
icon = NULL;
|
||||
|
||||
|
||||
@@ -443,6 +443,12 @@ VOID PhImageListWrapperRemove(
|
||||
__in INT Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGetStockApplicationIcon(
|
||||
__out_opt HICON *SmallIcon,
|
||||
__out_opt HICON *LargeIcon
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
HICON PhGetFileShellIcon(
|
||||
__in_opt PWSTR FileName,
|
||||
|
||||
@@ -1706,10 +1706,22 @@ PPH_STRING PhGetBaseName(
|
||||
|
||||
PPH_STRING PhGetSystemDirectory()
|
||||
{
|
||||
static PPH_STRING cachedSystemDirectory = NULL;
|
||||
|
||||
PPH_STRING systemDirectory;
|
||||
ULONG bufferSize;
|
||||
ULONG returnLength;
|
||||
|
||||
// Use the cached value if possible.
|
||||
|
||||
systemDirectory = cachedSystemDirectory;
|
||||
|
||||
if (systemDirectory)
|
||||
{
|
||||
PhReferenceObject(systemDirectory);
|
||||
return systemDirectory;
|
||||
}
|
||||
|
||||
bufferSize = 0x40;
|
||||
systemDirectory = PhCreateStringEx(NULL, bufferSize * 2);
|
||||
|
||||
@@ -1732,6 +1744,17 @@ PPH_STRING PhGetSystemDirectory()
|
||||
|
||||
PhTrimToNullTerminatorString(systemDirectory);
|
||||
|
||||
// Try to cache the value.
|
||||
if (_InterlockedCompareExchangePointer(
|
||||
&cachedSystemDirectory,
|
||||
systemDirectory,
|
||||
NULL
|
||||
) == NULL)
|
||||
{
|
||||
// Success, add one more reference for the cache.
|
||||
PhReferenceObject(systemDirectory);
|
||||
}
|
||||
|
||||
return systemDirectory;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user