forked from ritchielawrence/cmdow
-
Notifications
You must be signed in to change notification settings - Fork 1
/
wlist.cpp
704 lines (627 loc) · 18.3 KB
/
wlist.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
#include "header.h"
static HWND max_handle;
static int max_level;
static DWORD max_pid;
static int len_handle, len_level, len_pid, len_image;
static int len_begin;
//+---------------------------------------------------------------------------
// Function: GetMyHandle
//
// Synopsis: Determines handle of this console window
//
// Arguments: None
//
// Returns: Handle of this console window (which could theoretically be NULL)
//
// Notes:
//
//----------------------------------------------------------------------------
HWND GetMyHandle(void)
{
return GetConsoleWindow();
}
//+---------------------------------------------------------------------------
// Function: GetWindowList
//
// Synopsis: Causes ALL windows to be enumerated
//
// Arguments: [*w] pointer to WLIST structure
//
// Returns: none
//
// Notes: This function first gets info about the desktop window by a call to
// GetWindowInf, then enumerates all top level windows, with call to
// EnumWindows, the callback function get windows info, then uses recursion to
// enumerate child windows of each toplevel window
//
//----------------------------------------------------------------------------
void GetWindowList(struct WLIST *w)
{
struct WLIST *wptr = w;
GetWindowInf(GetDesktopWindow(), w);
EnumWindows( (WNDENUMPROC) GetWindowListProc, (LPARAM) &wptr);
}
//+---------------------------------------------------------------------------
// Function: GetWindowListProc
//
// Synopsis: This is the callback function defined by EnumWindows in
// GetWindowList. The O/S calls this function with a handle to every toplevel
// window.
//
// Arguments: [hwnd] Window handle supplied by O/S
// [wptrptr] pointer to pointer to WLIST structure. Application
// defined parameter supplied by GetWindowList.
//
// Returns: TRUE to tell O/S its ready for (and wants) the next window handle
//
// Notes: wptrptr is the current head of the list. Everytime function is called
// by O/S it dynamically creates a new WLIST structure that's linked to the
// original pointer. The w pointer is then aimed at the new struct and info
// about the window is gathered. If the window is a toplevel window (->level==1)
// then a call to EnumChildWindows is made, again using this function as the
// callback
//
//----------------------------------------------------------------------------
BOOL CALLBACK GetWindowListProc(HWND hwnd, LPARAM wptrptr)
{
struct WLIST **pwptr = (struct WLIST **) wptrptr;
struct WLIST *w = *pwptr;
//
// create a new WLIST struct
//
w->next = (struct WLIST *) HeapAlloc(GetProcessHeap(), 0, sizeof(struct WLIST));
if(!(w->next)) Quit(MEMERR);
//
// point to the new struct, then gather window info
//
w = *pwptr = w->next;
GetWindowInf(hwnd, w);
//
// make sure 'next' pointer is NULL terminated in case this is the last record.
//
w->next = NULL;
//
// If this is a toplevel window, then enumerate all its child windows
//
if(w->level==1) EnumChildWindows(hwnd, (WNDENUMPROC) GetWindowListProc, wptrptr);
return TRUE;
}
//+---------------------------------------------------------------------------
// Function: GetWindowInf
//
// Synopsis: Gathers information about a window and stores it in a WLIST struct
//
// Arguments: [hwnd] handle of the window to gather info about
// [*w] pointer to a WLIST struct
//
// Returns: FALSE if window does not exist, otherwise TRUE
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL GetWindowInf(HWND hwnd, struct WLIST *w)
{
#define MAX_CLASSNAME_LEN 63
int len;
HWND parent;
POINT pt;
RECT rect;
//
// get the desktop window only once
//
static HWND desktop = GetDesktopWindow();
//
// check window handle exists
//
if(!IsWindow(hwnd)) return FALSE;
//
// gather some window info
//
w->hwnd = hwnd;
w->styles = GetWindowLong(hwnd, GWL_STYLE);
w->exstyles = GetWindowLong(hwnd, GWL_EXSTYLE);
w->owner = GetWindow(hwnd, GW_OWNER);
w->parent = parent = GetParent(hwnd);
//
// determine window's level. 0=desktop, 1=toplevel, 2+ = child
//
if(hwnd == desktop) w->level = 0;
else if( (parent == w->owner) || (parent == desktop) ) w->level = 1;
else {
w->level = 1;
while( (parent != NULL) && (parent != desktop) ) {
w->level++;
parent = GetParent(parent);
}
}
//
// Get window's coords and determine width and height
//
GetWindowRect(hwnd, &rect);
w->left = rect.left;
w->top = rect.top;
w->width = rect.right - rect.left;
w->height = rect.bottom - rect.top;
//
// if child window, convert top left coords to position relative to parent window
//
if(w->level >1) {
pt.x = w->left;
pt.y = w->top;
ScreenToClient(w->parent, &pt);
w->left = pt.x;
w->top = pt.y;
}
//
// get process id
//
GetWindowThreadProcessId(hwnd, &w->pid);
//
// get the name of the executable that created the window
//
w->image = GetImageName(w->pid);
//
// Get the window caption if it has one, otherwise use the window's classname
//
len = GetWindowTextLength(hwnd);
if(!len) len = MAX_CLASSNAME_LEN;
w->caption = (char *) HeapAlloc(GetProcessHeap(), 0, sizeof(char) * (len + 1) );
if(!(w->caption)) Quit(MEMERR);
if(GetWindowTextLength(hwnd)) {
GetWindowText(hwnd, w->caption, len + 1);
for (char *p = w->caption; *p; ++p) {
if (*p == '\n') *p = '_';
}
}
else GetClassName(hwnd, w->caption, len + 1);
return TRUE;
}
//+---------------------------------------------------------------------------
// Function: FreeWindowList
//
// Synopsis: Release the memory used by the window list
//
// Arguments: [*w] pointer to WLIST structure
//
// Returns: none
//
// Notes:
//
//----------------------------------------------------------------------------
void FreeWindowList(struct WLIST *w)
{
struct WLIST *n;
HeapFree(GetProcessHeap(), 0, w->caption);
n = w->next;
w->next = NULL;
while(n) {
w = n;
n = n->next;
HeapFree(GetProcessHeap(), 0, w->caption);
HeapFree(GetProcessHeap(), 0, w);
}
}
static void LstWinLen(struct WLIST *w, BOOL tb)
{
max_handle = 0;
max_level = max_pid = len_image = 0;
while(w) {
if (!tb || IsTaskbarWindow(w)) {
if (max_handle < w->hwnd) max_handle = w->hwnd;
if (max_level < w->level) max_level = w->level;
if (max_pid < w->pid) max_pid = w->pid;
int len = lstrlen(w->image);
if (len_image < len) len_image = len;
}
w = w->next;
}
len_handle = (DWORD_PTR)max_handle > 0xFFFFFFF ? 8 :
(DWORD_PTR)max_handle > 0xFFFFFF ? 7 : 6;
len_level = (max_level > 99) ? 3 : (max_level > 9) ? 2 : 1;
len_pid = (max_pid > 9999) ? 5 : 4;
len_begin = 2 + len_handle + 1 + len_level + 1 + len_pid + 1 + 16;
if (len_image < 8) len_image = 8;
}
void PrintWindowInfHeadings(BOOL showpos, BOOL fullcapt)
{
printf("%-*s%*s%*s -Window status- ",
len_handle + 2, "Handle",
len_level + 1, "Lev",
len_pid + (len_level != 1), "Pid");
//
// if showing window position and size, then print their headings
//
if(showpos) {
printf(" Left Top Width Height ");
len_begin += 28;
}
printf("%-*sCaption\n", fullcapt ? len_image + 1 :
showpos && len_pid == 5 ? 8 : 9, "Image");
}
void LstWin(struct WLIST *w, struct ARGS *a)
{
static int headings;
const char *MinMaxRes, *ActiveInactive, *VisibleHidden, *EnabledDisabled;
if( (!headings++) ) {
LstWinLen(w, a->listopts & SHOWTB);
if( !(a->listopts & BARE) ) PrintWindowInfHeadings(a->listopts & SHOWPOS, a->listopts & FULLCAPT);
}
if(a->listopts & SHOWTB)
if(!IsTaskbarWindow(w)) return;
MinMaxRes = (w->styles & WS_MINIMIZE) ? "Min" :
(w->styles & WS_MAXIMIZE) ? "Max" :
"Res";
ActiveInactive = (GetForegroundWindow() == w->hwnd) ? "Act" : "Ina";
VisibleHidden = (w->styles & WS_VISIBLE) ? "Vis" : "Hid";
EnabledDisabled = (w->styles & WS_DISABLED) ? "Dis" : "Ena";
printf("0x%.*lX %*i %*lu %s %s %s %s ",
len_handle, (unsigned long) w->hwnd,
len_level, w->level,
len_pid, (unsigned long) w->pid,
MinMaxRes, ActiveInactive, EnabledDisabled, VisibleHidden);
if(a->listopts & SHOWPOS) {
printf("%6d %6d %6d %6d ", w->left, w->top, w->width, w->height);
}
if(a->listopts & FULLCAPT) {
printf("%-*s %s\n", len_image, w->image, w->caption);
}
else {
printf("%-8.8s %.*s\n",
w->image, 79 - 9 - len_begin, w->caption);
}
}
//+---------------------------------------------------------------------------
// Function: IsTaskbarWindow
//
// Synopsis: Determines if specified is shown on the taskbar
//
// Arguments: [*w] Pointer to a WLIST struct holding information about the
// window by a call to GetWindowInfo()
//
// Returns: TRUE if window is on the taskbar, FALSE if not
//
// Notes: I couldn't find any documentation on this but it appears a window is
// shown on the taskbar if: -
// > it's not hidden AND
// > does not have WS_EX_TOOLWINDOW style AND
// > does not have an owner AND
// > is level 1
//
//----------------------------------------------------------------------------
BOOL IsTaskbarWindow(struct WLIST *w)
{
if( (!(w->styles & WS_VISIBLE)) ||
(w->exstyles & WS_EX_TOOLWINDOW) ||
w->owner || (w->level != 1) ) return FALSE;
else return TRUE;
}
//+---------------------------------------------------------------------------
// Function: SetFGWindow
//
// Synopsis: Set the foreground window
//
// Arguments: [hwnd] handle to window to become foreground window
//
// Returns: None
//
// Notes: On W2K, if HKCU\Control Panel\Desktop\ForegroundLockTimeout != 0, as
// by default, then the O/S will not allow a background window to set
// the foreground window. I've worked around this by first activating this
// window, which by being the foreground window gets permission from the
// O/S to set another foreground window
//
//----------------------------------------------------------------------------
void SetFGWindow(HWND hwnd)
{
int Res;
DWORD FLT; /* ForegroundLockTimeout */
//
// Read HKCU\Control Panel\Desktop\ForegroundLockTimeout, Res != 0 if read
//
Res = SystemParametersInfo(0x2000, 0, (PVOID) &FLT, 0x0000);
//
// if FLT was read and is not zero, then activate this window first, so it gets
// permission to set a new foreground window
//
if(Res && FLT) SetForegroundWindow(GetMyHandle());
SetForegroundWindow(hwnd);
}
//
// Maximize window, if window hidden it will unhide itself, if disabled, stays disabled
//
void MaxWin(struct WLIST *w, struct ARGS *a)
{
HWND tmp;
//
// just in case maximized window gets focus, activate window that had focus
//
tmp = GetForegroundWindow();
ShowWindowAsync(w->hwnd, SW_MAXIMIZE);
if(tmp != GetForegroundWindow()) SetFGWindow(tmp);
}
//
// Minimize window, if window hidden it will become visible, if disabled, stays disabled
//
void MinWin(struct WLIST *w, struct ARGS *a)
{
HWND tmp;
//
// just in case maximized window gets focus, activate window that had focus
//
tmp = GetForegroundWindow();
ShowWindowAsync(w->hwnd, SW_MINIMIZE);
if(tmp != GetForegroundWindow()) SetFGWindow(tmp);
}
//
// Restore
//
void ResWin(struct WLIST *w, struct ARGS *a)
{
HWND tmp;
tmp = GetForegroundWindow();
// if was min, then res may make it active
// win was max, then min - then res will max it, res again will restore it
ShowWindowAsync(w->hwnd, SW_SHOWNOACTIVATE);
if(tmp != GetForegroundWindow()) SetFGWindow(tmp);
}
//
// Activate the window, if window is hidden, it gets focus but stays hidden
//
void ActWin(struct WLIST *w, struct ARGS *a)
{
SetFGWindow(w->hwnd);
}
//
// Inactivate window
//
void InaWin(struct WLIST *w, struct ARGS *a)
{
//
// only activate another window if specified window actually has focus
//
if(w->hwnd == GetForegroundWindow()) AltTab();
}
//
// Enable window
//
void EnaWin(struct WLIST *w, struct ARGS *a)
{
EnableWindow(w->hwnd, TRUE);
}
//
// Disable window
//
void DisWin(struct WLIST *w, struct ARGS *a)
{
EnableWindow(w->hwnd, FALSE);
}
//
// Hide the window
//
void HidWin(struct WLIST *w, struct ARGS *a)
{
ShowWindowAsync(w->hwnd, SW_HIDE);
}
//
// Make the window visible
//
void VisWin(struct WLIST *w, struct ARGS *a)
{
ShowWindowAsync(w->hwnd, SW_SHOW);
}
//
// Politely ask the window to close
//
void ClsWin(struct WLIST *w, struct ARGS *a)
{
PostMessage(w->hwnd, WM_CLOSE, 0, 0);
}
//
// End process associated with window (all windows with same Pid are killed!!!)
//
void EndWin(struct WLIST *w, struct ARGS *a)
{
HANDLE hProcess;
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, w->pid);
if(hProcess) {
TerminateProcess(hProcess, 1);
CloseHandle(hProcess);
}
}
//
// Rename window to new caption
//
void RenWin(struct WLIST *w, struct ARGS *a)
{
//
// If being asked to rename this console window, then launch CMDOW as a detached
// process with appropriate arguments
//
if(w->hwnd != a->myhwnd) {
SetWindowText(w->hwnd, a->newcapt);
return;
}
STARTUPINFO sInfo;
sInfo.cb = sizeof(STARTUPINFO);
sInfo.lpReserved = NULL;
sInfo.lpDesktop = NULL;
sInfo.lpTitle = NULL;
sInfo.dwFlags = 0;
sInfo.dwFillAttribute = 0;
sInfo.wShowWindow = SW_SHOW;
sInfo.cbReserved2 = 0;
sInfo.lpReserved2 = NULL;
int i;
char buf[20];
char *cmdline;
//
// Build the commandline to rename this console window
//
ltoa((long) a->myhwnd, buf, 16);
i = lstrlen(a->exename);
i += lstrlen(" 0x");
i += lstrlen(buf);
i += lstrlen(" /_RENAME_MYCONSOLE_WINDOW ");
i += lstrlen(a->newcapt);
// 2004-12-19 added line below
i += lstrlen("\"\"");
cmdline = (char *) HeapAlloc(GetProcessHeap(), 0, sizeof(char) * (i + 1));
if(!cmdline) Quit(MEMERR);
lstrcpy(cmdline, a->exename);
lstrcat(cmdline, " 0x");
lstrcat(cmdline, buf);
lstrcat(cmdline, " /_RENAME_MYCONSOLE_WINDOW ");
// 2004-12-19 added line below
lstrcat(cmdline, "\"");
lstrcat(cmdline, a->newcapt);
// 2004-12-19 added line below
lstrcat(cmdline, "\"");
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof pi);
//BOOL retval;
//retval =
CreateProcess(
NULL,
cmdline,
NULL,
NULL,
FALSE,
CREATE_NO_WINDOW,
NULL,
NULL,
&sInfo,
&pi
);
return;
}
//
// Retrieve the bounding rectangle of a window: the monitor's work area for a
// top-level window; otherwise the parent's client area
//
void GetBounds(struct WLIST *w, RECT &r)
{
if(w->level > 1) {
GetClientRect(w->parent, &r);
}
else {
HMONITOR monitor = MonitorFromWindow(w->hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(monitor, &mi);
r = mi.rcWork;
}
}
//
// Move window to new top left coords
//
void MovWin(struct WLIST *w, struct ARGS *a)
{
int left = a->left, top = a->top;
if(a->movopts) {
RECT r;
GetBounds(w, r);
if(a->movopts & MOVHORZPC) left = (r.right - r.left) * left / 100;
if(a->movopts & MOVLEFT) left += r.left;
if(a->movopts & MOVRIGHT) left = r.right - left - w->width;
if(a->movopts & MOVVERTPC) top = (r.bottom - r.top) * top / 100;
if(a->movopts & MOVTOP) top += r.top;
if(a->movopts & MOVBOTTOM) top = r.bottom - top - w->height;
}
MoveWindow(w->hwnd, left, top, w->width, w->height, TRUE);
}
//
// Resize window to new height and width
//
void SizWin(struct WLIST *w, struct ARGS *a)
{
int left = w->left, top = w->top;
int width = a->width, height = a->height;
if(a->sizopts & (SIZWIDTHPC | SIZHEIGHTPC)) {
RECT r;
GetBounds(w, r);
if(a->sizopts & SIZWIDTHPC) width = (r.right - r.left) * width / 100;
if(a->sizopts & SIZHEIGHTPC) height = (r.bottom - r.top) * height / 100;
}
if(a->sizopts & SIZLEFT) left += w->width - width;
if(a->sizopts & SIZTOP) top += w->height - height;
MoveWindow(w->hwnd, left, top, width, height, TRUE);
}
//
// Run
//
void RunWin(struct WLIST *w, struct ARGS *a)
{
#define SHELLEXEC_SUCCESS 33
int RetVal;
RetVal = (int) ShellExecute(NULL, NULL, a->file, a->params, NULL, a->sw_state);
if(RetVal < SHELLEXEC_SUCCESS) Quit(EXEERR);
}
//+---------------------------------------------------------------------------
// Function: AltTab
//
// Synopsis: Activates taskbar window with the lowest Z order. In the event of
// there being no taskbar windows, the desktop is activated.
//
// Arguments: None
//
// Returns: None
//
// Notes: User would typically use this feature to scroll through all windows
// on the taskbar (ie with a time delay between each call). By activating
// the lowest window, this moves to the top of the Z order, and all other
// move down one. If this function was to activate the next window in the
// Z order, then repeated calls to this function would only alternate
// between two windows (as happens when repeatedly pressing [Alt]-[Tab])
//
//----------------------------------------------------------------------------
void AltTab(void)
{
HWND hwnd, me;
struct WLIST w;
long styles;
//
// a handle to any toplevel window is required, so may as well use this
// console's handle, as guaranteed to exist
//
me = GetMyHandle();
//
// now get a toplevel window with the lowest Z order, and collect its info
//
hwnd = GetWindow(me, GW_HWNDLAST);
GetWindowInf(hwnd, &w);
//
// search up the Z order for first window on the taskbar, and collect its info
//
while( (!IsTaskbarWindow(&w)) && hwnd) {
hwnd = GetNextWindow(hwnd, GW_HWNDPREV);
GetWindowInf(hwnd, &w);
}
//
// hwnd maybe NULL if there weren't any taskbar windows, in which case do nothing
//
if(hwnd) SetFGWindow(hwnd);
//
// if window is minimized then restore it
//
styles = GetWindowLong(hwnd, GWL_STYLE);
if(styles & WS_MINIMIZE) {
w.hwnd = hwnd;
ResWin(&w, NULL);
}
}
void TopWin(struct WLIST *w, struct ARGS *a)
{
SetWindowPos(w->hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
);
}
void NotWin(struct WLIST *w, struct ARGS *a)
{
SetWindowPos(w->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
);
}
void SlpWin(struct WLIST *w, struct ARGS *a)
{
Sleep(a->sleep);
}