VOID PhpRemoveServiceItem( _In_ PPH_SERVICE_ITEM ServiceItem ) { PhRemoveEntryHashtable(PhServiceHashtable, &ServiceItem); PhDereferenceObject(ServiceItem); }
__assumeLocked VOID EtpRemoveDiskItem( __in PET_DISK_ITEM DiskItem ) { RemoveEntryList(&DiskItem->AgeListEntry); PhRemoveEntryHashtable(EtDiskHashtable, &DiskItem); PhDereferenceObject(DiskItem); }
__assumeLocked VOID PhpRemoveModuleItem( __in PPH_MODULE_PROVIDER ModuleProvider, __in PPH_MODULE_ITEM ModuleItem ) { PhRemoveEntryHashtable(ModuleProvider->ModuleHashtable, &ModuleItem); PhDereferenceObject(ModuleItem); }
__assumeLocked VOID PhpRemoveThreadItem( __in PPH_THREAD_PROVIDER ThreadProvider, __in PPH_THREAD_ITEM ThreadItem ) { PhRemoveEntryHashtable(ThreadProvider->ThreadHashtable, &ThreadItem); PhDereferenceObject(ThreadItem); }
VOID DeleteDbObject( _In_ PDB_OBJECT Object ) { PhRemoveEntryHashtable(ObjectDb, &Object); PhDereferenceObject(Object->Name); PhDereferenceObject(Object->Comment); PhFree(Object); }
VOID EtDiskProcessFileEvent( __in PET_ETW_FILE_EVENT Event ) { PH_KEY_VALUE_PAIR pair; PPH_KEY_VALUE_PAIR realPair; if (!EtDiskEnabled) return; if (Event->Type == EtEtwFileCreateType || Event->Type == EtEtwFileRundownType) { pair.Key = Event->FileObject; pair.Value = NULL; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhAddEntryHashtableEx(EtFileNameHashtable, &pair, NULL); PhSwapReference2(&realPair->Value, PhCreateStringEx(Event->FileName.Buffer, Event->FileName.Length)); PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } else if (Event->Type == EtEtwFileDeleteType) { pair.Key = Event->FileObject; PhAcquireQueuedLockExclusive(&EtFileNameHashtableLock); realPair = PhFindEntryHashtable(EtFileNameHashtable, &pair); if (realPair) { PhDereferenceObject(realPair->Value); PhRemoveEntryHashtable(EtFileNameHashtable, &pair); } PhReleaseQueuedLockExclusive(&EtFileNameHashtableLock); } }
LRESULT CALLBACK PhpExtendedListViewWndProc( __in HWND hwnd, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PPH_EXTLV_CONTEXT context; WNDPROC oldWndProc; context = (PPH_EXTLV_CONTEXT)GetProp(hwnd, PhpMakeExtLvContextAtom()); oldWndProc = context->OldWndProc; switch (uMsg) { case WM_DESTROY: { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc); if (context->TickHashtable) PhDereferenceObject(context->TickHashtable); PhFree(context); RemoveProp(hwnd, PhpMakeExtLvContextAtom()); } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case HDN_ITEMCLICK: { HWND headerHandle; headerHandle = (HWND)CallWindowProc(context->OldWndProc, hwnd, LVM_GETHEADER, 0, 0); if (header->hwndFrom == headerHandle) { LPNMHEADER header2 = (LPNMHEADER)header; if (header2->iItem == context->SortColumn) { if (context->TriState) { if (context->SortOrder == AscendingSortOrder) context->SortOrder = DescendingSortOrder; else if (context->SortOrder == DescendingSortOrder) context->SortOrder = NoSortOrder; else context->SortOrder = AscendingSortOrder; } else { if (context->SortOrder == AscendingSortOrder) context->SortOrder = DescendingSortOrder; else context->SortOrder = AscendingSortOrder; } } else { context->SortColumn = header2->iItem; context->SortOrder = AscendingSortOrder; } PhSetHeaderSortIcon(headerHandle, context->SortColumn, context->SortOrder); ExtendedListView_SortItems(hwnd); } } break; } } break; case WM_REFLECT + WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_CUSTOMDRAW: { if (header->hwndFrom == hwnd) { LPNMLVCUSTOMDRAW customDraw = (LPNMLVCUSTOMDRAW)header; switch (customDraw->nmcd.dwDrawStage) { case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW; case CDDS_ITEMPREPAINT: { LVITEM item; PH_ITEM_STATE itemState; BOOLEAN colorChanged = FALSE; HFONT newFont = NULL; item.mask = LVIF_STATE; item.iItem = (INT)customDraw->nmcd.dwItemSpec; item.iSubItem = 0; item.stateMask = LVIS_STATEIMAGEMASK; CallWindowProc(oldWndProc, hwnd, LVM_GETITEM, 0, (LPARAM)&item); itemState = PH_GET_ITEM_STATE(item.state); if (!context->EnableState || itemState == NormalItemState) { if (context->ItemColorFunction) { customDraw->clrTextBk = context->ItemColorFunction( (INT)customDraw->nmcd.dwItemSpec, (PVOID)customDraw->nmcd.lItemlParam, context->Context ); colorChanged = TRUE; } if (context->ItemFontFunction) { newFont = context->ItemFontFunction( (INT)customDraw->nmcd.dwItemSpec, (PVOID)customDraw->nmcd.lItemlParam, context->Context ); } if (newFont) SelectObject(customDraw->nmcd.hdc, newFont); } else if (itemState == NewItemState) { customDraw->clrTextBk = context->NewColor; colorChanged = TRUE; } else if (itemState == RemovingItemState) { customDraw->clrTextBk = context->RemovingColor; colorChanged = TRUE; } if (colorChanged) { if (PhGetColorBrightness(customDraw->clrTextBk) > 100) // slightly less than half customDraw->clrText = RGB(0x00, 0x00, 0x00); else customDraw->clrText = RGB(0xff, 0xff, 0xff); } if (!newFont) return CDRF_DODEFAULT; else return CDRF_NEWFONT; } break; } } } break; } } break; case WM_SETCURSOR: { if (context->Cursor) { SetCursor(context->Cursor); return TRUE; } } break; case WM_UPDATEUISTATE: { // Disable focus rectangles by setting or masking out the flag where appropriate. switch (LOWORD(wParam)) { case UIS_SET: wParam |= UISF_HIDEFOCUS << 16; break; case UIS_CLEAR: case UIS_INITIALIZE: wParam &= ~(UISF_HIDEFOCUS << 16); break; } } break; case LVM_INSERTITEM: { LPLVITEM item = (LPLVITEM)lParam; INT index; if (!context->EnableState) break; // pass through if (!(item->mask & LVIF_STATE)) { item->mask |= LVIF_STATE; item->stateMask = LVIS_STATEIMAGEMASK; item->state = 0; } else { item->stateMask |= LVIS_STATEIMAGEMASK; item->state &= ~LVIS_STATEIMAGEMASK; } if (context->EnableStateHighlighting > 0) { item->state |= INDEXTOSTATEIMAGEMASK(NewItemState); } else { item->state = NormalItemState; } if ((index = (INT)CallWindowProc(oldWndProc, hwnd, LVM_INSERTITEM, 0, (LPARAM)item)) == -1) return -1; if (context->EnableStateHighlighting > 0) { PH_TICK_ENTRY entry; PhpEnsureTickHashtableCreated(context); entry.Id = ListView_MapIndexToID(hwnd, index); entry.TickCount = GetTickCount(); PhAddEntryHashtable(context->TickHashtable, &entry); } return index; } case LVM_DELETEITEM: { if (!context->EnableState) break; // pass through if (context->EnableStateHighlighting > 0) { LVITEM item; item.mask = LVIF_STATE | LVIF_PARAM; item.iItem = (INT)wParam; item.iSubItem = 0; item.stateMask = LVIS_STATEIMAGEMASK; item.state = INDEXTOSTATEIMAGEMASK(RemovingItemState); // IMPORTANT: // We need to null the param. This is important because the user // will most likely be storing pointers to heap allocations in // here, and free the allocation after it has deleted the // item. The user may allocate sometime in the future and receive // the same pointer as is stored here. The user may call // LVM_FINDITEM or LVM_GETNEXTITEM and find this item, which // is supposed to be deleted. It may then attempt to delete // this item *twice*, which leads to bad things happening, // including *not* deleting the item that the user wanted to delete. item.lParam = (LPARAM)NULL; CallWindowProc(context->OldWndProc, hwnd, LVM_SETITEM, 0, (LPARAM)&item); { PH_TICK_ENTRY localEntry; PPH_TICK_ENTRY entry; PhpEnsureTickHashtableCreated(context); localEntry.Id = ListView_MapIndexToID(hwnd, (INT)wParam); entry = PhAddEntryHashtableEx(context->TickHashtable, &localEntry, NULL); entry->TickCount = GetTickCount(); } return TRUE; } else { // The item may still be under state highlighting. if (context->TickHashtable) { PH_TICK_ENTRY entry; entry.Id = ListView_MapIndexToID(hwnd, (INT)wParam); PhRemoveEntryHashtable(context->TickHashtable, &entry); } } } break; case LVM_GETITEM: { LVITEM item; ULONG itemState; ULONG oldMask; ULONG oldStateMask; if (!context->EnableState) break; // pass through memcpy(&item, (LPLVITEM)lParam, sizeof(LVITEM)); oldMask = item.mask; oldStateMask = item.stateMask; if (!(item.mask & LVIF_STATE)) { item.mask |= LVIF_STATE; item.stateMask = LVIS_STATEIMAGEMASK; } else { item.stateMask |= LVIS_STATEIMAGEMASK; } if (!CallWindowProc(oldWndProc, hwnd, LVM_GETITEM, 0, (LPARAM)&item)) return FALSE; // Check if the item is being deleted. If so, pretend it doesn't // exist. itemState = PH_GET_ITEM_STATE(item.state); if (itemState == RemovingItemState) return FALSE; item.mask = oldMask; item.stateMask = oldStateMask; item.state &= item.stateMask; memcpy((LPLVITEM)lParam, &item, sizeof(LVITEM)); } return TRUE; case ELVM_ADDFALLBACKCOLUMN: { if (context->NumberOfFallbackColumns < PH_MAX_COMPARE_FUNCTIONS) context->FallbackColumns[context->NumberOfFallbackColumns++] = (ULONG)wParam; else return FALSE; } return TRUE; case ELVM_ADDFALLBACKCOLUMNS: { ULONG numberOfColumns = (ULONG)wParam; PULONG columns = (PULONG)lParam; if (context->NumberOfFallbackColumns + numberOfColumns <= PH_MAX_COMPARE_FUNCTIONS) { memcpy( &context->FallbackColumns[context->NumberOfFallbackColumns], columns, numberOfColumns * sizeof(ULONG) ); context->NumberOfFallbackColumns += numberOfColumns; } else { return FALSE; } } return TRUE; case ELVM_ENABLESTATE: { context->EnableState = !!wParam; } return TRUE; case ELVM_INIT: { PhSetHeaderSortIcon(ListView_GetHeader(hwnd), context->SortColumn, context->SortOrder); // HACK to fix tooltips showing behind Always On Top windows. SetWindowPos(ListView_GetToolTips(hwnd), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); // Make sure focus rectangles are disabled. SendMessage(hwnd, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0); } return TRUE; case ELVM_SETCOLUMNWIDTH: { ULONG column = (ULONG)wParam; LONG width = (LONG)lParam; if (width == ELVSCW_AUTOSIZE_REMAININGSPACE) { RECT clientRect; LONG availableWidth; ULONG i; LVCOLUMN lvColumn; GetClientRect(hwnd, &clientRect); availableWidth = clientRect.right; i = 0; lvColumn.mask = LVCF_WIDTH; while (TRUE) { if (i != column) { if (CallWindowProc(oldWndProc, hwnd, LVM_GETCOLUMN, i, (LPARAM)&lvColumn)) { availableWidth -= lvColumn.cx; } else { break; } } i++; } if (availableWidth >= 40) return CallWindowProc(oldWndProc, hwnd, LVM_SETCOLUMNWIDTH, column, availableWidth); } return CallWindowProc(oldWndProc, hwnd, LVM_SETCOLUMNWIDTH, column, width); } break; case ELVM_SETCOMPAREFUNCTION: { ULONG column = (ULONG)wParam; PPH_COMPARE_FUNCTION compareFunction = (PPH_COMPARE_FUNCTION)lParam; if (column >= PH_MAX_COMPARE_FUNCTIONS) return FALSE; context->CompareFunctions[column] = compareFunction; } return TRUE; case ELVM_SETCONTEXT: { context->Context = (PVOID)lParam; } return TRUE; case ELVM_SETCURSOR: { context->Cursor = (HCURSOR)lParam; } return TRUE; case ELVM_SETHIGHLIGHTINGDURATION: { context->HighlightingDuration = (ULONG)wParam; } return TRUE; case ELVM_SETITEMCOLORFUNCTION: { context->ItemColorFunction = (PPH_EXTLV_GET_ITEM_COLOR)lParam; } return TRUE; case ELVM_SETITEMFONTFUNCTION: { context->ItemFontFunction = (PPH_EXTLV_GET_ITEM_FONT)lParam; } return TRUE; case ELVM_SETNEWCOLOR: { context->NewColor = (COLORREF)wParam; } return TRUE; case ELVM_SETREDRAW: { if (wParam) context->EnableRedraw++; else context->EnableRedraw--; if (context->EnableRedraw == 1) { SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hwnd, NULL, FALSE); } else if (context->EnableRedraw == 0) { SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); } } return TRUE; case ELVM_SETREMOVINGCOLOR: { context->RemovingColor = (COLORREF)wParam; } return TRUE; case ELVM_SETSORT: { context->SortColumn = (ULONG)wParam; context->SortOrder = (PH_SORT_ORDER)lParam; PhSetHeaderSortIcon(ListView_GetHeader(hwnd), context->SortColumn, context->SortOrder); } return TRUE; case ELVM_SETSORTFAST: { context->SortFast = !!wParam; } return TRUE; case ELVM_SETSTATEHIGHLIGHTING: { if (wParam) context->EnableStateHighlighting++; else context->EnableStateHighlighting--; } return TRUE; case ELVM_SETTRISTATE: { context->TriState = !!wParam; } return TRUE; case ELVM_SETTRISTATECOMPAREFUNCTION: { context->TriStateCompareFunction = (PPH_COMPARE_FUNCTION)lParam; } return TRUE; case ELVM_SORTITEMS: { if (context->SortFast) { // This sort method is faster than the normal sort because our comparison function // doesn't have to call the list view window procedure to get the item lParam values. // The disadvantage of this method is that default sorting is not available - if a // column doesn't have a comparison function, it doesn't get sorted at all. ListView_SortItems( hwnd, PhpExtendedListViewCompareFastFunc, (LPARAM)context ); } else { ListView_SortItemsEx( hwnd, PhpExtendedListViewCompareFunc, (LPARAM)context ); } } return TRUE; case ELVM_TICK: { if ( context->EnableStateHighlighting > 0 && context->TickHashtable && context->TickHashtable->Count != 0 ) { PhListTick(context); } } return TRUE; } return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); }
static VOID PhListTick( __in PPH_EXTLV_CONTEXT Context ) { HWND hwnd = Context->Handle; ULONG tickCount; BOOLEAN redrawDisabled = FALSE; PPH_LIST itemsToRemove = NULL; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_TICK_ENTRY entry; if (!Context->TickHashtable) return; tickCount = GetTickCount(); // First pass PhBeginEnumHashtable(Context->TickHashtable, &enumContext); while (entry = PhNextEnumHashtable(&enumContext)) { LVITEM item; PH_ITEM_STATE itemState; if (PhRoundNumber(tickCount - entry->TickCount, PH_DURATION_MULT) < Context->HighlightingDuration) continue; item.mask = LVIF_STATE; item.iItem = ListView_MapIDToIndex(hwnd, entry->Id); item.iSubItem = 0; item.stateMask = LVIS_STATEIMAGEMASK; CallWindowProc(Context->OldWndProc, hwnd, LVM_GETITEM, 0, (LPARAM)&item); itemState = PH_GET_ITEM_STATE(item.state); if (itemState == NewItemState) { item.state = INDEXTOSTATEIMAGEMASK(NormalItemState); CallWindowProc(Context->OldWndProc, hwnd, LVM_SETITEM, 0, (LPARAM)&item); if (!itemsToRemove) itemsToRemove = PhCreateList(2); PhAddItemList(itemsToRemove, (PVOID)entry->Id); entry->TickCount = tickCount; } } // Second pass // This pass is specifically for deleting items. PhBeginEnumHashtable(Context->TickHashtable, &enumContext); while (entry = PhNextEnumHashtable(&enumContext)) { LVITEM item; PH_ITEM_STATE itemState; if (itemsToRemove) { if (PhFindItemList(itemsToRemove, (PVOID)entry->Id) != -1) continue; } if (PhRoundNumber(tickCount - entry->TickCount, PH_DURATION_MULT) < Context->HighlightingDuration) continue; item.mask = LVIF_STATE; item.iItem = ListView_MapIDToIndex(hwnd, entry->Id); item.iSubItem = 0; item.stateMask = LVIS_STATEIMAGEMASK; CallWindowProc(Context->OldWndProc, hwnd, LVM_GETITEM, 0, (LPARAM)&item); itemState = PH_GET_ITEM_STATE(item.state); if (itemState == RemovingItemState) { if (!redrawDisabled) { ExtendedListView_SetRedraw(hwnd, FALSE); redrawDisabled = TRUE; } CallWindowProc(Context->OldWndProc, hwnd, LVM_DELETEITEM, item.iItem, 0); if (!itemsToRemove) itemsToRemove = PhCreateList(2); PhAddItemList(itemsToRemove, (PVOID)entry->Id); entry->TickCount = tickCount; } } if (redrawDisabled) { ExtendedListView_SetRedraw(hwnd, TRUE); } if (itemsToRemove) { ULONG i; for (i = 0; i < itemsToRemove->Count; i++) { PH_TICK_ENTRY removeEntry; removeEntry.Id = (ULONG)itemsToRemove->Items[i]; PhRemoveEntryHashtable(Context->TickHashtable, &removeEntry); } PhDereferenceObject(itemsToRemove); } }