* added copy support to PE viewer

* moved cpysave to phlib

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4115 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
wj32
2011-02-28 05:41:35 +00:00
parent 0f89665695
commit bbda2bdb6c
23 changed files with 617 additions and 486 deletions
+1
View File
@@ -2,6 +2,7 @@ Process Hacker
2.13
* NEW/IMPROVED:
* Added copy support to PE viewer
* FIXED:
2.12
@@ -222,6 +222,7 @@
<ClCompile Include="..\phlib\circbuf.c" />
<ClCompile Include="..\phlib\collect.c" />
<ClCompile Include="..\phlib\colorbox.c" />
<ClCompile Include="..\phlib\cpysave.c" />
<ClCompile Include="..\phlib\data.c" />
<ClCompile Include="..\phlib\dspick.c" />
<ClCompile Include="..\phlib\emenu.c" />
@@ -266,7 +267,6 @@
<ClCompile Include="chdlg.c" />
<ClCompile Include="chproc.c" />
<ClCompile Include="cmdmode.c" />
<ClCompile Include="cpysave.c" />
<ClCompile Include="dbgcon.c" />
<ClCompile Include="findobj.c" />
<ClCompile Include="gdihndl.c" />
@@ -177,9 +177,6 @@
<ClCompile Include="cmdmode.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="cpysave.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="dbgcon.c">
<Filter>Process Hacker</Filter>
</ClCompile>
@@ -435,6 +432,9 @@
<ClCompile Include="sessshad.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="..\phlib\cpysave.c">
<Filter>phlib</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\phlib\circbuf_i.h">
+1
View File
@@ -22,6 +22,7 @@
#include <phapp.h>
#include <settings.h>
#include <cpysave.h>
#include "mxml/mxml.h"
#include <winsta.h>
#include <dbghelp.h>
-33
View File
@@ -1150,39 +1150,6 @@ BOOLEAN PhShowChooseProcessDialog(
__out PHANDLE ProcessId
);
// cpysave
#define PH_EXPORT_MODE_TABS 0
#define PH_EXPORT_MODE_SPACES 1
#define PH_EXPORT_MODE_CSV 2
PHAPPAPI
PPH_FULL_STRING PhGetTreeListText(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns
);
PPH_LIST PhGetProcessTreeListLines(
__in HWND TreeListHandle,
__in ULONG NumberOfNodes,
__in PPH_LIST RootNodes,
__in ULONG Mode
);
PPH_LIST PhGetGenericTreeListLines(
__in HWND TreeListHandle,
__in ULONG Mode
);
PPH_FULL_STRING PhGetListViewText(
__in HWND ListViewHandle
);
PPH_LIST PhGetListViewLines(
__in HWND ListViewHandle,
__in ULONG Mode
);
// findobj
VOID PhShowFindObjectsDialog();
@@ -303,6 +303,13 @@ VOID PhRemoveProcessTreeFilter(
PHAPPAPI
VOID PhApplyProcessTreeFilters();
PPH_LIST PhGetProcessTreeListLines(
__in HWND TreeListHandle,
__in ULONG NumberOfNodes,
__in PPH_LIST RootNodes,
__in ULONG Mode
);
VOID PhCopyProcessTree();
VOID PhWriteProcessTree(
+1
View File
@@ -24,6 +24,7 @@
#include <phapp.h>
#include <treelist.h>
#include <settings.h>
#include <cpysave.h>
#include <memsrch.h>
#include <symprv.h>
#include <emenu.h>
+1
View File
@@ -24,6 +24,7 @@
#include <procprpp.h>
#include <kphuser.h>
#include <settings.h>
#include <cpysave.h>
#include <emenu.h>
#include <phplug.h>
#include <windowsx.h>
+120
View File
@@ -23,6 +23,7 @@
#include <phapp.h>
#include <settings.h>
#include <phplug.h>
#include <cpysave.h>
VOID PhpEnableColumnCustomDraw(
__in HWND hwnd,
@@ -2131,6 +2132,125 @@ VOID PhApplyProcessTreeFilters()
TreeList_NodesStructured(ProcessTreeListHandle);
}
VOID PhpPopulateTableWithProcessNodes(
__in HWND TreeListHandle,
__in PPH_PROCESS_NODE Node,
__in ULONG Level,
__in PPH_STRING **Table,
__inout PULONG Index,
__in PULONG DisplayToId,
__in ULONG Columns
)
{
ULONG i;
for (i = 0; i < Columns; i++)
{
PH_TL_GETNODETEXT getNodeText;
PPH_STRING text;
getNodeText.Node = &Node->Node;
getNodeText.Id = DisplayToId[i];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
if (i != 0)
{
text = PhaCreateStringEx(getNodeText.Text.Buffer, getNodeText.Text.Length);
}
else
{
// If this is the first column in the row, add some indentation.
text = PhaCreateStringEx(
NULL,
getNodeText.Text.Length + Level * 2 * sizeof(WCHAR)
);
wmemset(text->Buffer, ' ', Level * 2);
memcpy(&text->Buffer[Level * 2], getNodeText.Text.Buffer, getNodeText.Text.Length);
}
Table[*Index][i] = text;
}
(*Index)++;
// Process the children.
for (i = 0; i < Node->Children->Count; i++)
{
PhpPopulateTableWithProcessNodes(
TreeListHandle,
Node->Children->Items[i],
Level + 1,
Table,
Index,
DisplayToId,
Columns
);
}
}
PPH_LIST PhGetProcessTreeListLines(
__in HWND TreeListHandle,
__in ULONG NumberOfNodes,
__in PPH_LIST RootNodes,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
// The number of rows in the table (including +1 for the column headers).
ULONG rows;
// The number of columns.
ULONG columns;
// A column display index to ID map.
ULONG displayToId[PHPRTLC_MAXIMUM];
// A column display index to text map.
PWSTR displayToText[PHPRTLC_MAXIMUM];
// The actual string table.
PPH_STRING **table;
ULONG i;
ULONG j;
// Use a local auto-pool to make memory mangement a bit less painful.
PhInitializeAutoPool(&autoPool);
rows = NumberOfNodes + 1;
// Create the display index to ID map.
PhMapDisplayIndexTreeList(TreeListHandle, PHPRTLC_MAXIMUM, displayToId, displayToText, &columns);
PhaCreateTextTable(&table, rows, columns);
// Populate the first row with the column headers.
for (i = 0; i < columns; i++)
{
table[0][i] = PhaCreateString(displayToText[i]);
}
// Go through the nodes in the process tree and populate each cell of the table.
j = 1; // index starts at one because the first row contains the column headers.
for (i = 0; i < RootNodes->Count; i++)
{
PhpPopulateTableWithProcessNodes(
TreeListHandle,
RootNodes->Items[i],
0,
table,
&j,
displayToId,
columns
);
}
lines = PhaFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
VOID PhCopyProcessTree()
{
PPH_FULL_STRING text;
+1
View File
@@ -14,6 +14,7 @@
#include "treelist.h"
#include "emenu.h"
#include "cpysave.h"
#include "phapppub.h"
#include "phplug.h"
+1
View File
@@ -23,6 +23,7 @@
#include <phapp.h>
#include <settings.h>
#include <phplug.h>
#include <cpysave.h>
BOOLEAN PhpServiceNodeHashtableCompareFunction(
__in PVOID Entry1,
@@ -2,7 +2,7 @@
* Process Hacker -
* copy/save code for listviews and treelists
*
* Copyright (C) 2010 wj32
* Copyright (C) 2010-2011 wj32
*
* This file is part of Process Hacker.
*
@@ -20,436 +20,12 @@
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include <phapp.h>
#include <phgui.h>
#include <treelist.h>
#include <cpysave.h>
#define TAB_SIZE 8
VOID PhapCreateTextTable(
__out PPH_STRING ***Table,
__in ULONG Rows,
__in ULONG Columns
);
PPH_LIST PhapFormatTextTable(
__in PPH_STRING **Table,
__in ULONG Rows,
__in ULONG Columns,
__in ULONG Mode
);
VOID PhpMapDisplayIndexTreeList(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns,
__out_ecount(MaximumNumberOfColumns) PULONG DisplayToId,
__out_ecount_opt(MaximumNumberOfColumns) PWSTR *DisplayToText,
__out PULONG NumberOfColumns
)
{
PH_TREELIST_COLUMN column;
ULONG i;
ULONG count;
count = 0;
for (i = 0; i < MaximumNumberOfColumns; i++)
{
column.Id = i;
if (TreeList_GetColumn(TreeListHandle, &column))
{
if (column.Visible)
{
if (column.DisplayIndex < MaximumNumberOfColumns)
{
DisplayToId[column.DisplayIndex] = i;
if (DisplayToText)
DisplayToText[column.DisplayIndex] = column.Text;
count++;
}
}
}
}
*NumberOfColumns = count;
}
PPH_FULL_STRING PhGetTreeListText(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns
)
{
PPH_FULL_STRING string;
PULONG displayToId;
ULONG rows;
ULONG columns;
ULONG i;
ULONG j;
displayToId = PhAllocate(MaximumNumberOfColumns * sizeof(ULONG));
PhpMapDisplayIndexTreeList(TreeListHandle, MaximumNumberOfColumns, displayToId, NULL, &columns);
rows = TreeList_GetVisibleNodeCount(TreeListHandle);
string = PhCreateFullString2(0x100);
for (i = 0; i < rows; i++)
{
PH_TL_GETNODETEXT getNodeText;
getNodeText.Node = TreeList_GetVisibleNode(TreeListHandle, i);
assert(getNodeText.Node);
if (!getNodeText.Node->Selected)
continue;
for (j = 0; j < columns; j++)
{
getNodeText.Id = displayToId[j];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
PhAppendFullStringEx(string, getNodeText.Text.Buffer, getNodeText.Text.Length);
PhAppendFullString2(string, L", ");
}
// Remove the trailing comma and space.
if (string->Length != 0)
PhRemoveFullString(string, string->Length / 2 - 2, 2);
PhAppendFullString2(string, L"\r\n");
}
PhFree(displayToId);
return string;
}
VOID PhpPopulateTableWithProcessNodes(
__in HWND TreeListHandle,
__in PPH_PROCESS_NODE Node,
__in ULONG Level,
__in PPH_STRING **Table,
__inout PULONG Index,
__in PULONG DisplayToId,
__in ULONG Columns
)
{
ULONG i;
for (i = 0; i < Columns; i++)
{
PH_TL_GETNODETEXT getNodeText;
PPH_STRING text;
getNodeText.Node = &Node->Node;
getNodeText.Id = DisplayToId[i];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
if (i != 0)
{
text = PhaCreateStringEx(getNodeText.Text.Buffer, getNodeText.Text.Length);
}
else
{
// If this is the first column in the row, add some indentation.
text = PhaCreateStringEx(
NULL,
getNodeText.Text.Length + Level * 2 * sizeof(WCHAR)
);
wmemset(text->Buffer, ' ', Level * 2);
memcpy(&text->Buffer[Level * 2], getNodeText.Text.Buffer, getNodeText.Text.Length);
}
Table[*Index][i] = text;
}
(*Index)++;
// Process the children.
for (i = 0; i < Node->Children->Count; i++)
{
PhpPopulateTableWithProcessNodes(
TreeListHandle,
Node->Children->Items[i],
Level + 1,
Table,
Index,
DisplayToId,
Columns
);
}
}
PPH_LIST PhGetProcessTreeListLines(
__in HWND TreeListHandle,
__in ULONG NumberOfNodes,
__in PPH_LIST RootNodes,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
// The number of rows in the table (including +1 for the column headers).
ULONG rows;
// The number of columns.
ULONG columns;
// A column display index to ID map.
ULONG displayToId[PHPRTLC_MAXIMUM];
// A column display index to text map.
PWSTR displayToText[PHPRTLC_MAXIMUM];
// The actual string table.
PPH_STRING **table;
ULONG i;
ULONG j;
// Use a local auto-pool to make memory mangement a bit less painful.
PhInitializeAutoPool(&autoPool);
rows = NumberOfNodes + 1;
// Create the display index to ID map.
PhpMapDisplayIndexTreeList(TreeListHandle, PHPRTLC_MAXIMUM, displayToId, displayToText, &columns);
PhapCreateTextTable(&table, rows, columns);
// Populate the first row with the column headers.
for (i = 0; i < columns; i++)
{
table[0][i] = PhaCreateString(displayToText[i]);
}
// Go through the nodes in the process tree and populate each cell of the table.
j = 1; // index starts at one because the first row contains the column headers.
for (i = 0; i < RootNodes->Count; i++)
{
PhpPopulateTableWithProcessNodes(
TreeListHandle,
RootNodes->Items[i],
0,
table,
&j,
displayToId,
columns
);
}
lines = PhapFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
PPH_LIST PhGetGenericTreeListLines(
__in HWND TreeListHandle,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
ULONG rows;
ULONG columns;
ULONG numberOfNodes;
ULONG maxId;
PULONG displayToId;
PWSTR *displayToText;
PPH_STRING **table;
ULONG i;
ULONG j;
PhInitializeAutoPool(&autoPool);
numberOfNodes = TreeList_GetVisibleNodeCount(TreeListHandle);
maxId = TreeList_GetMaxId(TreeListHandle) + 1;
displayToId = PhAllocate(sizeof(ULONG) * maxId);
displayToText = PhAllocate(sizeof(PWSTR) * maxId);
rows = numberOfNodes + 1;
PhpMapDisplayIndexTreeList(TreeListHandle, maxId, displayToId, displayToText, &columns);
PhapCreateTextTable(&table, rows, columns);
for (i = 0; i < columns; i++)
table[0][i] = PhaCreateString(displayToText[i]);
for (i = 0; i < numberOfNodes; i++)
{
PPH_TREELIST_NODE node;
node = TreeList_GetVisibleNode(TreeListHandle, i);
if (node)
{
for (j = 0; j < columns; j++)
{
PH_TL_GETNODETEXT getNodeText;
getNodeText.Node = node;
getNodeText.Id = displayToId[j];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
table[i + 1][j] = PhaCreateStringEx(getNodeText.Text.Buffer, getNodeText.Text.Length);
}
}
else
{
for (j = 0; j < columns; j++)
{
table[i + 1][j] = PHA_DEREFERENCE(PhReferenceEmptyString());
}
}
}
PhFree(displayToText);
PhFree(displayToId);
lines = PhapFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
VOID PhapMapDisplayIndexListView(
__in HWND ListViewHandle,
__out_ecount(Count) PULONG DisplayToId,
__out_ecount_opt(Count) PPH_STRING *DisplayToText,
__in ULONG Count,
__out PULONG NumberOfColumns
)
{
LVCOLUMN lvColumn;
ULONG i;
ULONG count;
WCHAR buffer[128];
count = 0;
lvColumn.mask = LVCF_ORDER | LVCF_TEXT;
lvColumn.pszText = buffer;
lvColumn.cchTextMax = sizeof(buffer) / sizeof(WCHAR);
for (i = 0; i < Count; i++)
{
if (ListView_GetColumn(ListViewHandle, i, &lvColumn))
{
ULONG displayIndex;
displayIndex = (ULONG)lvColumn.iOrder;
assert(displayIndex < Count);
DisplayToId[displayIndex] = i;
if (DisplayToText)
DisplayToText[displayIndex] = PhaCreateString(buffer);
count++;
}
else
{
break;
}
}
*NumberOfColumns = count;
}
PPH_FULL_STRING PhGetListViewText(
__in HWND ListViewHandle
)
{
PPH_FULL_STRING string;
ULONG displayToId[100];
ULONG rows;
ULONG columns;
ULONG i;
ULONG j;
PhapMapDisplayIndexListView(ListViewHandle, displayToId, NULL, 100, &columns);
rows = ListView_GetItemCount(ListViewHandle);
string = PhCreateFullString2(0x100);
for (i = 0; i < rows; i++)
{
if (!(ListView_GetItemState(ListViewHandle, i, LVIS_SELECTED) & LVIS_SELECTED))
continue;
for (j = 0; j < columns; j++)
{
WCHAR buffer[512];
buffer[0] = 0;
ListView_GetItemText(ListViewHandle, i, j, buffer, sizeof(buffer) / sizeof(WCHAR));
PhAppendFullString2(string, buffer);
PhAppendFullString2(string, L", ");
}
// Remove the trailing comma and space.
if (string->Length != 0)
PhRemoveFullString(string, string->Length / 2 - 2, 2);
PhAppendFullString2(string, L"\r\n");
}
return string;
}
PPH_LIST PhGetListViewLines(
__in HWND ListViewHandle,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
ULONG rows;
ULONG columns;
ULONG displayToId[100];
PPH_STRING displayToText[100];
PPH_STRING **table;
ULONG i;
ULONG j;
PhInitializeAutoPool(&autoPool);
rows = ListView_GetItemCount(ListViewHandle) + 1; // +1 for column headers
// Create the display index/text to ID map.
PhapMapDisplayIndexListView(ListViewHandle, displayToId, displayToText, 100, &columns);
PhapCreateTextTable(&table, rows, columns);
// Populate the first row with the column headers.
for (i = 0; i < columns; i++)
table[0][i] = displayToText[i];
// Populate the other rows with text.
for (i = 1; i < rows; i++)
{
for (j = 0; j < columns; j++)
{
WCHAR buffer[512];
// Important: use this to bypass extlv's hooking.
// extlv only hooks LVM_GETITEM, not LVM_GETITEMTEXT.
buffer[0] = 0;
ListView_GetItemText(ListViewHandle, i - 1, j, buffer, sizeof(buffer) / sizeof(WCHAR));
table[i][j] = PhaCreateString(buffer);
}
}
lines = PhapFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
VOID PhpEscapeStringForCsv(
__inout PPH_STRING_BUILDER StringBuilder,
__in PPH_STRING String
@@ -496,7 +72,7 @@ VOID PhpEscapeStringForCsv(
PhAppendStringBuilderEx(StringBuilder, runStart, runLength * sizeof(WCHAR));
}
VOID PhapCreateTextTable(
VOID PhaCreateTextTable(
__out PPH_STRING ***Table,
__in ULONG Rows,
__in ULONG Columns
@@ -517,7 +93,7 @@ VOID PhapCreateTextTable(
*Table = table;
}
PPH_LIST PhapFormatTextTable(
PPH_LIST PhaFormatTextTable(
__in PPH_STRING **Table,
__in ULONG Rows,
__in ULONG Columns,
@@ -616,3 +192,297 @@ PPH_LIST PhapFormatTextTable(
return lines;
}
VOID PhMapDisplayIndexTreeList(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns,
__out_ecount(MaximumNumberOfColumns) PULONG DisplayToId,
__out_ecount_opt(MaximumNumberOfColumns) PWSTR *DisplayToText,
__out PULONG NumberOfColumns
)
{
PH_TREELIST_COLUMN column;
ULONG i;
ULONG count;
count = 0;
for (i = 0; i < MaximumNumberOfColumns; i++)
{
column.Id = i;
if (TreeList_GetColumn(TreeListHandle, &column))
{
if (column.Visible)
{
if (column.DisplayIndex < MaximumNumberOfColumns)
{
DisplayToId[column.DisplayIndex] = i;
if (DisplayToText)
DisplayToText[column.DisplayIndex] = column.Text;
count++;
}
}
}
}
*NumberOfColumns = count;
}
PPH_FULL_STRING PhGetTreeListText(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns
)
{
PPH_FULL_STRING string;
PULONG displayToId;
ULONG rows;
ULONG columns;
ULONG i;
ULONG j;
displayToId = PhAllocate(MaximumNumberOfColumns * sizeof(ULONG));
PhMapDisplayIndexTreeList(TreeListHandle, MaximumNumberOfColumns, displayToId, NULL, &columns);
rows = TreeList_GetVisibleNodeCount(TreeListHandle);
string = PhCreateFullString2(0x100);
for (i = 0; i < rows; i++)
{
PH_TL_GETNODETEXT getNodeText;
getNodeText.Node = TreeList_GetVisibleNode(TreeListHandle, i);
assert(getNodeText.Node);
if (!getNodeText.Node->Selected)
continue;
for (j = 0; j < columns; j++)
{
getNodeText.Id = displayToId[j];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
PhAppendFullStringEx(string, getNodeText.Text.Buffer, getNodeText.Text.Length);
PhAppendFullString2(string, L", ");
}
// Remove the trailing comma and space.
if (string->Length != 0)
PhRemoveFullString(string, string->Length / 2 - 2, 2);
PhAppendFullString2(string, L"\r\n");
}
PhFree(displayToId);
return string;
}
PPH_LIST PhGetGenericTreeListLines(
__in HWND TreeListHandle,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
ULONG rows;
ULONG columns;
ULONG numberOfNodes;
ULONG maxId;
PULONG displayToId;
PWSTR *displayToText;
PPH_STRING **table;
ULONG i;
ULONG j;
PhInitializeAutoPool(&autoPool);
numberOfNodes = TreeList_GetVisibleNodeCount(TreeListHandle);
maxId = TreeList_GetMaxId(TreeListHandle) + 1;
displayToId = PhAllocate(sizeof(ULONG) * maxId);
displayToText = PhAllocate(sizeof(PWSTR) * maxId);
rows = numberOfNodes + 1;
PhMapDisplayIndexTreeList(TreeListHandle, maxId, displayToId, displayToText, &columns);
PhaCreateTextTable(&table, rows, columns);
for (i = 0; i < columns; i++)
table[0][i] = PhaCreateString(displayToText[i]);
for (i = 0; i < numberOfNodes; i++)
{
PPH_TREELIST_NODE node;
node = TreeList_GetVisibleNode(TreeListHandle, i);
if (node)
{
for (j = 0; j < columns; j++)
{
PH_TL_GETNODETEXT getNodeText;
getNodeText.Node = node;
getNodeText.Id = displayToId[j];
PhInitializeEmptyStringRef(&getNodeText.Text);
TreeList_GetNodeText(TreeListHandle, &getNodeText);
table[i + 1][j] = PhaCreateStringEx(getNodeText.Text.Buffer, getNodeText.Text.Length);
}
}
else
{
for (j = 0; j < columns; j++)
{
table[i + 1][j] = PHA_DEREFERENCE(PhReferenceEmptyString());
}
}
}
PhFree(displayToText);
PhFree(displayToId);
lines = PhaFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
VOID PhaMapDisplayIndexListView(
__in HWND ListViewHandle,
__out_ecount(Count) PULONG DisplayToId,
__out_ecount_opt(Count) PPH_STRING *DisplayToText,
__in ULONG Count,
__out PULONG NumberOfColumns
)
{
LVCOLUMN lvColumn;
ULONG i;
ULONG count;
WCHAR buffer[128];
count = 0;
lvColumn.mask = LVCF_ORDER | LVCF_TEXT;
lvColumn.pszText = buffer;
lvColumn.cchTextMax = sizeof(buffer) / sizeof(WCHAR);
for (i = 0; i < Count; i++)
{
if (ListView_GetColumn(ListViewHandle, i, &lvColumn))
{
ULONG displayIndex;
displayIndex = (ULONG)lvColumn.iOrder;
assert(displayIndex < Count);
DisplayToId[displayIndex] = i;
if (DisplayToText)
DisplayToText[displayIndex] = PhaCreateString(buffer);
count++;
}
else
{
break;
}
}
*NumberOfColumns = count;
}
PPH_FULL_STRING PhGetListViewText(
__in HWND ListViewHandle
)
{
PPH_FULL_STRING string;
ULONG displayToId[100];
ULONG rows;
ULONG columns;
ULONG i;
ULONG j;
PhaMapDisplayIndexListView(ListViewHandle, displayToId, NULL, 100, &columns);
rows = ListView_GetItemCount(ListViewHandle);
string = PhCreateFullString2(0x100);
for (i = 0; i < rows; i++)
{
if (!(ListView_GetItemState(ListViewHandle, i, LVIS_SELECTED) & LVIS_SELECTED))
continue;
for (j = 0; j < columns; j++)
{
WCHAR buffer[512];
buffer[0] = 0;
ListView_GetItemText(ListViewHandle, i, j, buffer, sizeof(buffer) / sizeof(WCHAR));
PhAppendFullString2(string, buffer);
PhAppendFullString2(string, L", ");
}
// Remove the trailing comma and space.
if (string->Length != 0)
PhRemoveFullString(string, string->Length / 2 - 2, 2);
PhAppendFullString2(string, L"\r\n");
}
return string;
}
PPH_LIST PhGetListViewLines(
__in HWND ListViewHandle,
__in ULONG Mode
)
{
PH_AUTO_POOL autoPool;
PPH_LIST lines;
ULONG rows;
ULONG columns;
ULONG displayToId[100];
PPH_STRING displayToText[100];
PPH_STRING **table;
ULONG i;
ULONG j;
PhInitializeAutoPool(&autoPool);
rows = ListView_GetItemCount(ListViewHandle) + 1; // +1 for column headers
// Create the display index/text to ID map.
PhaMapDisplayIndexListView(ListViewHandle, displayToId, displayToText, 100, &columns);
PhaCreateTextTable(&table, rows, columns);
// Populate the first row with the column headers.
for (i = 0; i < columns; i++)
table[0][i] = displayToText[i];
// Populate the other rows with text.
for (i = 1; i < rows; i++)
{
for (j = 0; j < columns; j++)
{
WCHAR buffer[512];
// Important: use this to bypass extlv's hooking.
// extlv only hooks LVM_GETITEM, not LVM_GETITEMTEXT.
buffer[0] = 0;
ListView_GetItemText(ListViewHandle, i - 1, j, buffer, sizeof(buffer) / sizeof(WCHAR));
table[i][j] = PhaCreateString(buffer);
}
}
lines = PhaFormatTextTable(table, rows, columns, Mode);
PhDeleteAutoPool(&autoPool);
return lines;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef _PH_CPYSAVE_H
#define _PH_CPYSAVE_H
#define PH_EXPORT_MODE_TABS 0
#define PH_EXPORT_MODE_SPACES 1
#define PH_EXPORT_MODE_CSV 2
VOID PhaCreateTextTable(
__out PPH_STRING ***Table,
__in ULONG Rows,
__in ULONG Columns
);
PPH_LIST PhaFormatTextTable(
__in PPH_STRING **Table,
__in ULONG Rows,
__in ULONG Columns,
__in ULONG Mode
);
VOID PhMapDisplayIndexTreeList(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns,
__out_ecount(MaximumNumberOfColumns) PULONG DisplayToId,
__out_ecount_opt(MaximumNumberOfColumns) PWSTR *DisplayToText,
__out PULONG NumberOfColumns
);
PHLIBAPI
PPH_FULL_STRING PhGetTreeListText(
__in HWND TreeListHandle,
__in ULONG MaximumNumberOfColumns
);
PPH_LIST PhGetGenericTreeListLines(
__in HWND TreeListHandle,
__in ULONG Mode
);
VOID PhaMapDisplayIndexListView(
__in HWND ListViewHandle,
__out_ecount(Count) PULONG DisplayToId,
__out_ecount_opt(Count) PPH_STRING *DisplayToText,
__in ULONG Count,
__out PULONG NumberOfColumns
);
PPH_FULL_STRING PhGetListViewText(
__in HWND ListViewHandle
);
PPH_LIST PhGetListViewLines(
__in HWND ListViewHandle,
__in ULONG Mode
);
#endif
+8 -8
View File
@@ -359,6 +359,14 @@ HWND PhCreateTreeListControlEx(
__in ULONG Style
);
__callback BOOLEAN NTAPI PhTreeListNullCallback(
__in HWND hwnd,
__in PH_TREELIST_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
);
PHLIBAPI
VOID PhInitializeTreeListNode(
__in PPH_TREELIST_NODE Node
@@ -410,12 +418,4 @@ PPH_STRING PhSaveTreeListColumnSettings(
__in HWND TreeListHandle
);
__callback BOOLEAN NTAPI PhTreeListNullCallback(
__in HWND hwnd,
__in PH_TREELIST_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
);
#endif
+2
View File
@@ -166,6 +166,7 @@
<ClCompile Include="circbuf.c" />
<ClCompile Include="collect.c" />
<ClCompile Include="colorbox.c" />
<ClCompile Include="cpysave.c" />
<ClCompile Include="data.c" />
<ClCompile Include="dspick.c" />
<ClCompile Include="emenu.c" />
@@ -224,6 +225,7 @@
<ClCompile Include="workqueue.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\cpysave.h" />
<ClInclude Include="include\kphapi.h" />
<ClInclude Include="include\ntpfapi.h" />
<ClInclude Include="include\ntzwapi.h" />
+6
View File
@@ -201,6 +201,9 @@
<ClCompile Include="workqueue.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cpysave.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\phsync.h">
@@ -425,6 +428,9 @@
<ClInclude Include="include\ntpfapi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\cpysave.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="pcre\pcre_printint.src" />
+11 -11
View File
@@ -2277,6 +2277,17 @@ static VOID PhpReloadThemeData(
}
}
__callback BOOLEAN NTAPI PhTreeListNullCallback(
__in HWND hwnd,
__in PH_TREELIST_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
)
{
return FALSE;
}
VOID PhInitializeTreeListNode(
__in PPH_TREELIST_NODE Node
)
@@ -2559,14 +2570,3 @@ PPH_STRING PhSaveTreeListColumnSettings(
return PhFinalStringBuilderString(&stringBuilder);
}
__callback BOOLEAN NTAPI PhTreeListNullCallback(
__in HWND hwnd,
__in PH_TREELIST_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
)
{
return FALSE;
}
+15
View File
@@ -9,8 +9,23 @@
extern PPH_STRING PvFileName;
#endif
// peprp
VOID PvPeProperties();
// libprp
VOID PvLibProperties();
// misc
VOID PvCopyListView(
__in HWND ListViewHandle
);
VOID PvHandleListViewNotifyForCopy(
__in LPARAM lParam,
__in HWND ListViewHandle
);
#endif
+5
View File
@@ -164,6 +164,11 @@ INT_PTR CALLBACK PvpLibExportsDlgProc(
ExtendedListView_SortItems(lvHandle);
}
break;
case WM_NOTIFY:
{
PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
+56
View File
@@ -0,0 +1,56 @@
/*
* Process Hacker -
* PE viewer
*
* Copyright (C) 2011 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include <peview.h>
#include <cpysave.h>
// Copied from appsup.c
VOID PvCopyListView(
__in HWND ListViewHandle
)
{
PPH_FULL_STRING text;
text = PhGetListViewText(ListViewHandle);
PhSetClipboardStringEx(ListViewHandle, text->Buffer, text->Length);
PhDereferenceObject(text);
}
VOID PvHandleListViewNotifyForCopy(
__in LPARAM lParam,
__in HWND ListViewHandle
)
{
if (((LPNMHDR)lParam)->hwndFrom == ListViewHandle)
{
LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)lParam;
switch (keyDown->wVKey)
{
case 'C':
if (GetKeyState(VK_CONTROL) < 0)
PvCopyListView(ListViewHandle);
break;
}
}
}
+16
View File
@@ -21,6 +21,7 @@
*/
#include <peview.h>
#include <cpysave.h>
#define PVM_CHECKSUM_DONE (WM_APP + 1)
@@ -353,6 +354,11 @@ INT_PTR CALLBACK PvpPeGeneralDlgProc(
}
}
break;
case WM_NOTIFY:
{
PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
@@ -428,6 +434,11 @@ INT_PTR CALLBACK PvpPeImportsDlgProc(
ExtendedListView_SortItems(lvHandle);
}
break;
case WM_NOTIFY:
{
PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
@@ -504,6 +515,11 @@ INT_PTR CALLBACK PvpPeExportsDlgProc(
ExtendedListView_SortItems(lvHandle);
}
break;
case WM_NOTIFY:
{
PvHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
+1
View File
@@ -182,6 +182,7 @@
<ItemGroup>
<ClCompile Include="libprp.c" />
<ClCompile Include="main.c" />
<ClCompile Include="misc.c" />
<ClCompile Include="peprp.c" />
</ItemGroup>
<ItemGroup>
@@ -24,6 +24,9 @@
<ClCompile Include="peprp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="misc.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\peview.h">