Process Hacker
procrec.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * process record properties
4  *
5  * Copyright (C) 2010 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phapp.h>
24 
25 typedef struct _PROCESS_RECORD_CONTEXT
26 {
27  PPH_PROCESS_RECORD Record;
28  HICON FileIcon;
30 
31 INT_PTR CALLBACK PhpProcessRecordDlgProc(
32  _In_ HWND hwndDlg,
33  _In_ UINT uMsg,
34  _In_ WPARAM wParam,
35  _In_ LPARAM lParam
36  );
37 
39  _In_ HWND ParentWindowHandle,
40  _In_ PPH_PROCESS_RECORD Record
41  )
42 {
43  PROCESS_RECORD_CONTEXT context;
44 
45  context.Record = Record;
46 
47  DialogBoxParam(
49  MAKEINTRESOURCE(IDD_PROCRECORD),
50  ParentWindowHandle,
52  (LPARAM)&context
53  );
54 }
55 
57  _In_ PLARGE_INTEGER Time
58  )
59 {
60  LARGE_INTEGER time;
61  LARGE_INTEGER currentTime;
62  SYSTEMTIME timeFields;
63  PPH_STRING timeRelativeString;
64  PPH_STRING timeString;
65 
66  time = *Time;
67  PhQuerySystemTime(&currentTime);
68  timeRelativeString = PhAutoDereferenceObject(PhFormatTimeSpanRelative(currentTime.QuadPart - time.QuadPart));
69 
70  PhLargeIntegerToLocalSystemTime(&timeFields, &time);
71  timeString = PhaFormatDateTime(&timeFields);
72 
73  return PhaFormatString(L"%s ago (%s)", timeRelativeString->Buffer, timeString->Buffer);
74 }
75 
76 FORCEINLINE PWSTR PhpGetStringOrNa(
77  _In_ PPH_STRING String
78  )
79 {
80  if (String)
81  return String->Buffer;
82  else
83  return L"N/A";
84 }
85 
86 INT_PTR CALLBACK PhpProcessRecordDlgProc(
87  _In_ HWND hwndDlg,
88  _In_ UINT uMsg,
89  _In_ WPARAM wParam,
90  _In_ LPARAM lParam
91  )
92 {
93  PPROCESS_RECORD_CONTEXT context = NULL;
94 
95  if (uMsg == WM_INITDIALOG)
96  {
97  context = (PPROCESS_RECORD_CONTEXT)lParam;
98  SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
99  }
100  else
101  {
102  context = (PPROCESS_RECORD_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
103 
104  if (uMsg == WM_DESTROY)
105  {
106  RemoveProp(hwndDlg, PhMakeContextAtom());
107  }
108  }
109 
110  if (!context)
111  return FALSE;
112 
113  switch (uMsg)
114  {
115  case WM_INITDIALOG:
116  {
117  PH_IMAGE_VERSION_INFO versionInfo;
118  BOOLEAN versionInfoInitialized;
119  PPH_STRING processNameString;
120  PPH_PROCESS_ITEM processItem;
121 
122  if (!PH_IS_FAKE_PROCESS_ID(context->Record->ProcessId))
123  {
124  processNameString = PhaFormatString(L"%s (%u)",
125  context->Record->ProcessName->Buffer, (ULONG)context->Record->ProcessId);
126  }
127  else
128  {
129  processNameString = context->Record->ProcessName;
130  }
131 
132  PhCenterWindow(hwndDlg, GetParent(hwndDlg));
133  SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), TRUE);
134  SetWindowText(hwndDlg, processNameString->Buffer);
135 
136  SetDlgItemText(hwndDlg, IDC_PROCESSNAME, processNameString->Buffer);
137 
138  if (processItem = PhReferenceProcessItemForRecord(context->Record))
139  {
140  PPH_PROCESS_ITEM parentProcess;
141 
142  if (parentProcess = PhReferenceProcessItemForParent(
143  processItem->ParentProcessId,
144  processItem->ProcessId,
145  &processItem->CreateTime
146  ))
147  {
148  CLIENT_ID clientId;
149 
150  clientId.UniqueProcess = parentProcess->ProcessId;
151  clientId.UniqueThread = NULL;
152 
153  SetDlgItemText(hwndDlg, IDC_PARENT,
154  ((PPH_STRING)PhAutoDereferenceObject(PhGetClientIdNameEx(&clientId, parentProcess->ProcessName)))->Buffer);
155 
156  PhDereferenceObject(parentProcess);
157  }
158  else
159  {
160  SetDlgItemText(hwndDlg, IDC_PARENT, PhaFormatString(L"Non-existent process (%u)",
161  (ULONG)context->Record->ParentProcessId)->Buffer);
162  }
163 
164  PhDereferenceObject(processItem);
165  }
166  else
167  {
168  SetDlgItemText(hwndDlg, IDC_PARENT, PhaFormatString(L"Unknown process (%u)",
169  (ULONG)context->Record->ParentProcessId)->Buffer);
170 
171  EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), FALSE);
172  }
173 
174  memset(&versionInfo, 0, sizeof(PH_IMAGE_VERSION_INFO));
175  versionInfoInitialized = FALSE;
176 
177  if (context->Record->FileName)
178  {
179  if (PhInitializeImageVersionInfo(&versionInfo, context->Record->FileName->Buffer))
180  versionInfoInitialized = TRUE;
181  }
182 
183  context->FileIcon = PhGetFileShellIcon(PhGetString(context->Record->FileName), L".exe", TRUE);
184 
185  SendMessage(GetDlgItem(hwndDlg, IDC_OPENFILENAME), BM_SETIMAGE, IMAGE_BITMAP,
186  (LPARAM)PH_LOAD_SHARED_IMAGE(MAKEINTRESOURCE(IDB_FOLDER), IMAGE_BITMAP));
187  SendMessage(GetDlgItem(hwndDlg, IDC_FILEICON), STM_SETICON,
188  (WPARAM)context->FileIcon, 0);
189 
190  SetDlgItemText(hwndDlg, IDC_NAME, PhpGetStringOrNa(versionInfo.FileDescription));
191  SetDlgItemText(hwndDlg, IDC_COMPANYNAME, PhpGetStringOrNa(versionInfo.CompanyName));
192  SetDlgItemText(hwndDlg, IDC_VERSION, PhpGetStringOrNa(versionInfo.FileVersion));
193  SetDlgItemText(hwndDlg, IDC_FILENAME, PhpGetStringOrNa(context->Record->FileName));
194 
195  if (versionInfoInitialized)
196  PhDeleteImageVersionInfo(&versionInfo);
197 
198  if (!context->Record->FileName)
199  EnableWindow(GetDlgItem(hwndDlg, IDC_OPENFILENAME), FALSE);
200 
201  SetDlgItemText(hwndDlg, IDC_CMDLINE, PhpGetStringOrNa(context->Record->CommandLine));
202 
203  if (context->Record->CreateTime.QuadPart != 0)
204  SetDlgItemText(hwndDlg, IDC_STARTED, PhpaGetRelativeTimeString(&context->Record->CreateTime)->Buffer);
205  else
206  SetDlgItemText(hwndDlg, IDC_STARTED, L"N/A");
207 
208  if (context->Record->ExitTime.QuadPart != 0)
209  SetDlgItemText(hwndDlg, IDC_TERMINATED, PhpaGetRelativeTimeString(&context->Record->ExitTime)->Buffer);
210  else
211  SetDlgItemText(hwndDlg, IDC_TERMINATED, L"N/A");
212 
213  SetDlgItemInt(hwndDlg, IDC_SESSIONID, context->Record->SessionId, FALSE);
214  }
215  break;
216  case WM_DESTROY:
217  {
218  if (context->FileIcon)
219  DestroyIcon(context->FileIcon);
220  }
221  break;
222  case WM_COMMAND:
223  {
224  switch (LOWORD(wParam))
225  {
226  case IDCANCEL:
227  case IDOK:
228  {
229  EndDialog(hwndDlg, IDOK);
230  }
231  break;
232  case IDC_OPENFILENAME:
233  {
234  if (context->Record->FileName)
235  PhShellExploreFile(hwndDlg, context->Record->FileName->Buffer);
236  }
237  break;
238  case IDC_PROPERTIES:
239  {
240  PPH_PROCESS_ITEM processItem;
241 
242  if (processItem = PhReferenceProcessItemForRecord(context->Record))
243  {
245  PhDereferenceObject(processItem);
246  }
247  else
248  {
249  PhShowError(hwndDlg, L"The process has already terminated; only the process record is available.");
250  }
251  }
252  break;
253  }
254  }
255  break;
256  }
257 
258  return FALSE;
259 }