Compare commits
224 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5998c235f1 | |||
|
|
caa84730cc | ||
|
|
7410e6ddb1 | ||
|
|
04d5187a36 | ||
|
|
56084fefb7 | ||
|
|
51561cd0ac | ||
|
|
c58b785b7b | ||
|
|
841128b2f3 | ||
|
|
13b4657c5b | ||
|
|
8f6af5bba9 | ||
|
|
b679f71607 | ||
|
|
154bed9106 | ||
|
|
b13ce0578b | ||
|
|
9c6fe40c1c | ||
|
|
ca4b30e1d7 | ||
|
|
793c6a626f | ||
|
|
892db32a81 | ||
|
|
69a624e0f9 | ||
|
|
4a8ef09334 | ||
|
|
cc62e8dc38 | ||
|
|
b335db994a | ||
|
|
21271a7c4b | ||
|
|
0fa28c9e3e | ||
|
|
2c1fa58da6 | ||
|
|
f6b7c29d2c | ||
|
|
d2342e80f5 | ||
|
|
306621f084 | ||
|
|
f0ae48cd10 | ||
|
|
aef812ae92 | ||
|
|
50a290d57e | ||
|
|
93ca902e1f | ||
|
|
7234547e3d | ||
|
|
8f5bdce45b | ||
|
|
fdc0d28ab7 | ||
|
|
e0670bea6d | ||
|
|
bcd6716fcb | ||
|
|
e3187f62c3 | ||
|
|
174edb0aaa | ||
|
|
654dbf6be0 | ||
|
|
7ea2d75f37 | ||
|
|
7602f6df4d | ||
|
|
e8e91d87cd | ||
|
|
91216a8778 | ||
|
|
f94859613c | ||
|
|
1beddc7695 | ||
|
|
69baa0e28c | ||
|
|
34026dbc8d | ||
|
|
fef15a326d | ||
|
|
a07aace682 | ||
|
|
39d2983852 | ||
|
|
e7ad120d92 | ||
|
|
8939e71a99 | ||
|
|
7a3c1ae092 | ||
|
|
67513d7c23 | ||
|
|
360aa81df6 | ||
|
|
c6cfed377a | ||
|
|
f18779ef28 | ||
|
|
a570e61c8b | ||
|
|
28e7fa0ad7 | ||
|
|
972c56a15b | ||
|
|
7dd1875e1d | ||
|
|
f1e0a17b3d | ||
|
|
c1dd3ae999 | ||
|
|
309ce4702b | ||
|
|
5e878f98cf | ||
|
|
2c86c796f5 | ||
|
|
2e7dafbbac | ||
|
|
961cedb975 | ||
|
|
e990647e1b | ||
|
|
9079225a29 | ||
|
|
6e4d38544e | ||
|
|
5d17a98ca0 | ||
|
|
bce106ce5f | ||
|
|
2b32d3f8f8 | ||
|
|
000ecc527f | ||
|
|
e7bcb43cd1 | ||
|
|
28e5ec10fc | ||
|
|
55ea523d34 | ||
|
|
52fc4cdcab | ||
|
|
1c273f6337 | ||
|
|
edd9da0ce4 | ||
|
|
c9581062f6 | ||
|
|
e0fa6632cd | ||
|
|
4054dac5f1 | ||
|
|
291e1f0d16 | ||
|
|
97784e31ae | ||
|
|
475d868825 | ||
|
|
f718eb4d51 | ||
|
|
c5c5d6d714 | ||
|
|
59f7eb76bd | ||
|
|
ef8b514527 | ||
|
|
39229500f6 | ||
|
|
493abda875 | ||
|
|
1a17c89074 | ||
|
|
bbf9941fd4 | ||
|
|
012ad25462 | ||
|
|
06e32d9063 | ||
|
|
ef0a73d819 | ||
|
|
bd4712a7db | ||
|
|
710fc5aecd | ||
|
|
39ed21c334 | ||
|
|
c1e2d5279d | ||
|
|
ab9e9d9b18 | ||
|
|
ea0c0773e6 | ||
|
|
efb000f4ec | ||
|
|
36a6d1a888 | ||
|
|
67e821a33c | ||
|
|
69a1ea88f5 | ||
|
|
0c0f9c765e | ||
|
|
b8c4a712f9 | ||
|
|
b07bcbfa6d | ||
|
|
531400b700 | ||
|
|
15d3bcca5c | ||
|
|
fa1ac0dfc9 | ||
|
|
14c5e5560b | ||
|
|
6f312892e8 | ||
|
|
1ed794d640 | ||
|
|
c43c176538 | ||
|
|
fd51e72432 | ||
|
|
403cfafedb | ||
|
|
866402a7b3 | ||
|
|
717d744195 | ||
|
|
2c16c265ca | ||
|
|
82c2d2d15f | ||
|
|
925bb43a6d | ||
|
|
b02cc93c6d | ||
|
|
e6b36b3b94 | ||
|
|
51e907a7d0 | ||
|
|
6533f53aaa | ||
|
|
f2b1af5cba | ||
|
|
b14c11f98e | ||
|
|
99fbc7392c | ||
|
|
ab20d2ec8c | ||
|
|
678eef08c9 | ||
|
|
4269ded2f6 | ||
|
|
44270fd601 | ||
|
|
c7d3ae27d1 | ||
|
|
3245d93436 | ||
|
|
7e3fcb1fc3 | ||
|
|
607330267f | ||
|
|
5d7536d5fd | ||
|
|
5e6f59f946 | ||
|
|
cbb7373cc1 | ||
|
|
58e6635bae | ||
|
|
b2413ad307 | ||
|
|
49d22b8a13 | ||
|
|
d4aa908ea2 | ||
|
|
4dfb5d8554 | ||
|
|
2ff4ee0c9c | ||
|
|
24a17d0287 | ||
|
|
6943fc563b | ||
|
|
b8466d176b | ||
|
|
48c8f542bc | ||
|
|
d16b7254da | ||
|
|
349a9a9d0d | ||
|
|
2aa96bc024 | ||
|
|
e0724dc0c7 | ||
|
|
99d851f368 | ||
|
|
ef30558e0a | ||
|
|
1ff398ad70 | ||
|
|
cbe1fb7551 | ||
|
|
1b8ec3b152 | ||
|
|
84f106938d | ||
|
|
f761ac6cf7 | ||
|
|
3cbe91cf89 | ||
|
|
fd3abe1795 | ||
|
|
42f0f268d9 | ||
|
|
6ce9166a92 | ||
|
|
e19e3d399b | ||
|
|
d7a3802571 | ||
|
|
a074441a99 | ||
|
|
59937a8690 | ||
|
|
613b998348 | ||
|
|
e0461949ae | ||
|
|
acc63b5aa6 | ||
|
|
64d69162ab | ||
|
|
6ac03d7a1b | ||
|
|
0d237c5039 | ||
|
|
714fe3a4ae | ||
|
|
5d0a3f1ccf | ||
|
|
d7e5d10209 | ||
|
|
d01b18e035 | ||
|
|
6c40ba9886 | ||
|
|
0d0e37b561 | ||
|
|
bda528569b | ||
|
|
9bb0dfd24b | ||
|
|
ef88804240 | ||
|
|
a494e057c9 | ||
|
|
7910340133 | ||
|
|
b736576829 | ||
|
|
94f4e71b20 | ||
|
|
9e67a3d81b | ||
|
|
2972d54777 | ||
|
|
6aaabd480a | ||
|
|
e400645956 | ||
|
|
77512dd72d | ||
|
|
8fb871de34 | ||
|
|
d41f0b868b | ||
|
|
b9cea5b8e6 | ||
|
|
745030da99 | ||
|
|
739c56e314 | ||
|
|
78f612e684 | ||
|
|
1bb6e0b05a | ||
|
|
541c86b4a2 | ||
|
|
f632229b3c | ||
|
|
488070e73d | ||
|
|
f8578360f8 | ||
|
|
a4f7046760 | ||
|
|
364afc7438 | ||
|
|
bbde0b6acb | ||
|
|
3441f7771a | ||
|
|
6302272d96 | ||
|
|
7409d6cc41 | ||
|
|
db71fb2ab3 | ||
|
|
84c62213d7 | ||
|
|
437703e26d | ||
|
|
fbdb45b4df | ||
|
|
ba276117d7 | ||
|
|
35a28f698f | ||
|
|
bf2c7ce3da | ||
|
|
4095f501c1 | ||
|
|
2632512881 | ||
|
|
af3e493085 | ||
|
|
d875363d72 |
22
.github/workflows/msbuild.yml
vendored
@@ -16,23 +16,23 @@ env:
|
||||
# Path to the solution file relative to the root of the project.
|
||||
SOLUTION_FILE_PATH: .
|
||||
|
||||
# Configuration type to build.
|
||||
# You can convert this to a build matrix if you need coverage of multiple configuration types.
|
||||
# https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
BUILD_CONFIGURATION: Release
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
BUILD_CONFIGURATION: [Release, Debug]
|
||||
BUILD_PLATFORM: [x64, x86]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4.1.1
|
||||
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
- name: Restore NuGet packages
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
@@ -42,4 +42,10 @@ jobs:
|
||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||
# Add additional options to the MSBuild command line here (like platform or verbosity level).
|
||||
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
|
||||
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}}
|
||||
run: msbuild /m /p:Configuration=${{matrix.BUILD_CONFIGURATION}} /p:Platform=${{matrix.BUILD_PLATFORM}} ${{env.SOLUTION_FILE_PATH}}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4.3.1
|
||||
with:
|
||||
name: progmgr-${{matrix.BUILD_CONFIGURATION}}-${{matrix.BUILD_PLATFORM}}
|
||||
path: ${{env.SOLUTION_FILE_PATH}}/bin
|
||||
13
.gitignore
vendored
@@ -44,16 +44,23 @@
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
/.vs/Program-Manager-II
|
||||
/.vs
|
||||
/planning
|
||||
/progmgr/RCa10968
|
||||
/progmgr/RCa*
|
||||
/progmgr/icons/Thumbs.db
|
||||
/bin/
|
||||
/misc/supermiumman.png
|
||||
/bin.7z
|
||||
*.zip
|
||||
*.res
|
||||
*.suo
|
||||
*.user
|
||||
*.sdf
|
||||
*.opensdf
|
||||
|
||||
release
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Vortesys
|
||||
Copyright (c) 2023-2024 Vortesys
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.6.33723.286
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "progmgr", "progmgr\progmgr.vcxproj", "{B76B940D-B61A-456E-8569-72F64CF91AFB}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProgMgr", "ProgMgr\ProgMgr.vcxproj", "{B76B940D-B61A-456E-8569-72F64CF91AFB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
16
README.md
@@ -1,15 +1,21 @@
|
||||

|
||||
|
||||
[](https://github.com/Vortesys/Program-Manager-II/releases) [](https://github.com/Vortesys/Program-Manager-II/releases)
|
||||
# Program Manager *II* for Windows NT
|
||||

|
||||
|
||||
## What is Program Manager?
|
||||
Program Manager was the shell that shipped with Microsoft Windows by default from Windows 3.0/NT 3.1 to 3.11/NT 3.51. The Program Manager shell was included with Windows as an option until Windows 2000. The new Program Manager is a shell that aims to mimic the original desktop metaphor that the original Program Manager was designed for while adding modern amenities.
|
||||
Program Manager was the default shell for Windows (NT) 3.x. The Program Manager shell was included as an optional component in Windows until Windows 2000. It contained a basic task manager, a group-based program launcher and a shutdown dialog.
|
||||
|
||||
## So, what about Program Manager II?
|
||||
Program Manager II is a shell designed to supercede the original Microsoft Program Manager with better compatibility, stability, and usability. It's currently in alpha and doesn't contain all of the necessary functionality, but progress is being made.
|
||||
|
||||
## What does it run on?
|
||||
Program Manager should run on ~~every AMD64 version of Windows and every 32-bit version back to 2000. The ultimate goal is to run on NT 3.51 just as well as it can run on Windows 11~~ Windows Vista and above.
|
||||
Program Manager II will run on Windows Vista and above with no problem. Support for XP and older is not guaranteed, nor will it be ported to 9x.
|
||||
|
||||
## Where do I get it?
|
||||
The [releases page](https://github.com/Vortesys/Program-Manager-II/releases) will contain the latest version of Program Manager.
|
||||
The [releases page](https://github.com/Vortesys/Program-Manager-II/releases) will contain the latest "stable" version of Program Manager II. Build artifacts can be found for most commits made since April and contain pre-release builds.
|
||||
|
||||
## What's planned for the future?
|
||||
You can look through all of the issues in the issue tracker with the Beta milestone attached to them to see what's planned. Otherwise, you can message me, 'freedom_usa' on Discord and ask about the direction of the project after feature parity is reached.
|
||||
|
||||
## How can I help?
|
||||
Submitting [issues](https://github.com/Vortesys/Program-Manager-II/issues) with bug reports, suggestions or comments always helps. If you're able to, contributing with a [pull request](https://github.com/Vortesys/Program-Manager-II/pulls) is much appreciated.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
7z a -r "%~dp0bin\bin.7z" "%~dp0bin\*.exe"
|
||||
WinRAR a -r "%~dp0bin\bin.rar" "%~dp0bin\*.exe"
|
||||
del /s "%~dp0bin\*.exe"
|
||||
pause
|
||||
37
build.cmd
Normal file
@@ -0,0 +1,37 @@
|
||||
@echo off
|
||||
|
||||
set DIR_ROOT=%~dp0.
|
||||
set DIR_PROGMGR=%DIR_ROOT%\progmgr
|
||||
set DIR_RELEASE=%DIR_ROOT%\release
|
||||
|
||||
rmdir /S /Q "%DIR_RELEASE%" > nul 2>&1
|
||||
if not exist "%DIR_RELEASE%" mkdir "%DIR_RELEASE%"
|
||||
|
||||
git rev-parse HEAD > %DIR_RELEASE%\.git_hash
|
||||
set /P GIT_HASH=<%DIR_RELEASE%\.git_hash
|
||||
set "GIT_HASH=%GIT_HASH:~0,8%"
|
||||
|
||||
if "%1" == "debug" (
|
||||
set CL=/MT /Od /Zi /RTC1 /Fdprogmgr.pdb /fsanitize=address /DUNICODE /D_DEBUG /DPROGMGR_DEBUG /DPROGMGR_GIT_HASH="%GIT_HASH%"
|
||||
set LINK=/DEBUG
|
||||
) else (
|
||||
set CL=/O1 /GS- /DUNICODE /DNDEBUG /DPROGMGR_RELEASE /DPROGMGR_GIT_HASH="%GIT_HASH%"
|
||||
rem set LINK=/NODEFAULTLIB /OPT:REF /OPT:ICF
|
||||
set LINK=/OPT:REF /OPT:ICF
|
||||
)
|
||||
|
||||
pushd "%DIR_RELEASE%"
|
||||
rc /nologo /DPROGMGR_GIT_HASH="""%GIT_HASH%""" /i "%DIR_PROGMGR%" "%DIR_PROGMGR%\lang\dlg_en-US.rc"
|
||||
rc /nologo /DPROGMGR_GIT_HASH="""%GIT_HASH%""" /i "%DIR_PROGMGR%" "%DIR_PROGMGR%\lang\res_en-US.rc"
|
||||
rc /nologo /DPROGMGR_GIT_HASH="""%GIT_HASH%""" /i "%DIR_PROGMGR%" "%DIR_PROGMGR%\resource.rc"
|
||||
cl /nologo /W3 /WX /MP /Feprogmgr.exe ^
|
||||
"%DIR_PROGMGR%\*.c" ^
|
||||
"%DIR_PROGMGR%\resource.res" ^
|
||||
"%DIR_PROGMGR%\lang\dlg_en-US.res" ^
|
||||
"%DIR_PROGMGR%\lang\res_en-US.res" ^
|
||||
/link /INCREMENTAL:NO /SUBSYSTEM:WINDOWS /FIXED /merge:_RDATA=.rdata ^
|
||||
/MANIFEST:EMBED /MANIFESTINPUT:%DIR_PROGMGR%\progmgr.exe.manifest ^
|
||||
kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib ^
|
||||
secur32.lib comdlg32.lib pathcch.lib shlwapi.lib version.lib ^
|
||||
comctl32.lib uxtheme.lib
|
||||
popd
|
||||
BIN
misc/pman.pdn
BIN
misc/pman2.png
|
Before Width: | Height: | Size: 20 KiB |
BIN
misc/pman64.png
|
Before Width: | Height: | Size: 11 KiB |
BIN
misc/progman.jpg
Normal file
|
After Width: | Height: | Size: 212 KiB |
@@ -1,203 +0,0 @@
|
||||
/* * * * * * * *\
|
||||
DESKTOP.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
DESCRIPTION -
|
||||
Program Manager's desktop window.
|
||||
Only visible as the default shell.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#include "progmgr.h"
|
||||
#include "resource.h"
|
||||
// #define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <CommCtrl.h>
|
||||
|
||||
/* Structures */
|
||||
typedef struct _mrp
|
||||
{
|
||||
HWND hWndMRP;
|
||||
DWORD dwFlags;
|
||||
} MRP, * PMRP;
|
||||
|
||||
/* Defines */
|
||||
// MRP Flags
|
||||
#define MRP_ICONIFIED 0x000000001
|
||||
#define MRP_FLASHING 0x000000002
|
||||
// Miscellaneous
|
||||
#define MAXTITLELEN 256
|
||||
#define ID_LISTVIEW 1000
|
||||
|
||||
/* Variables */
|
||||
HWND hWndDesktop;
|
||||
HWND hWndListView;
|
||||
RECT rcRoot;
|
||||
|
||||
/* Functions */
|
||||
LRESULT CALLBACK DeskWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
HWND CreateListView(HWND hWndParent, RECT rc);
|
||||
|
||||
/* * * *\
|
||||
CreateDesktopWindow -
|
||||
Creates the invisible desktop window.
|
||||
RETURNS -
|
||||
True if successful, false if unsuccessful.
|
||||
\* * * */
|
||||
BOOL CreateDesktopWindow()
|
||||
{
|
||||
MSG msg = { 0 };
|
||||
WNDCLASSEX wc = { 0 };
|
||||
WCHAR szBuffer[MAX_PATH];
|
||||
WCHAR szClass[16];
|
||||
|
||||
// If we fail, we shouldn't be here anyways.
|
||||
//if (GetShellWindow())
|
||||
// return FALSE;
|
||||
|
||||
// Get size of the root HWND
|
||||
GetWindowRect(GetDesktopWindow(), &rcRoot);
|
||||
|
||||
// Load the window class string
|
||||
LoadString(hAppInstance, IDS_DTCLASS, szClass, ARRAYSIZE(szClass));
|
||||
|
||||
// Refresh the wallpaper...
|
||||
SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, szBuffer, 0);
|
||||
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, szBuffer, SPIF_SENDCHANGE);
|
||||
|
||||
// Reset the work area (removes dead-space after switching from another shell)
|
||||
// May have unintended consequences. Doesn't work with multiple monitors.
|
||||
SystemParametersInfo(SPI_SETWORKAREA, 0, &rcRoot, SPIF_SENDCHANGE);
|
||||
|
||||
// Register the desktop window
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.lpfnWndProc = DeskWndProc;
|
||||
wc.hInstance = hAppInstance;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_WINDOW);
|
||||
wc.style = CS_NOCLOSE;
|
||||
wc.lpszClassName = szClass;
|
||||
if (!RegisterClassEx(&wc))
|
||||
return FALSE;
|
||||
|
||||
if (CreateWindowEx(WS_EX_TOOLWINDOW, wc.lpszClassName,
|
||||
NULL, WS_VISIBLE, rcRoot.left, rcRoot.top,
|
||||
rcRoot.right - rcRoot.left, rcRoot.bottom - rcRoot.top,
|
||||
NULL, NULL, hAppInstance, NULL) == NULL);
|
||||
return 2;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0) > 0)
|
||||
{
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
DeskWndProc -
|
||||
Program Manager's desktop window procedure.
|
||||
RETURNS -
|
||||
Zero if nothing, otherwise returns the good stuff.
|
||||
\* * * */
|
||||
LRESULT CALLBACK DeskWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_CREATE:
|
||||
// Populate hWndDesktop
|
||||
hWndDesktop = hWnd;
|
||||
|
||||
// Set the window position to shell
|
||||
// SetShellWindow(hWndDesktop);
|
||||
ShowWindow(hWndDesktop, SW_MAXIMIZE);
|
||||
|
||||
// Strip the border from the desktop window
|
||||
SetWindowLongPtr(hWndDesktop, GWL_STYLE, WS_POPUP);
|
||||
|
||||
// Size the window to take up the primary monitor's desktop
|
||||
SetWindowPos(hWndDesktop, HWND_BOTTOM,
|
||||
rcRoot.left, rcRoot.top, rcRoot.right - rcRoot.left, rcRoot.bottom - rcRoot.top,
|
||||
SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
|
||||
// Finally, bring Program Manager to the foreground.
|
||||
SetWindowPos(hWndProgMgr, HWND_TOP,
|
||||
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
// Finally, Create the ListView control
|
||||
//hWndListView = CreateListView(hWndDesktop, rcRoot);
|
||||
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
case WM_DPICHANGED:
|
||||
case WM_DISPLAYCHANGE:
|
||||
case WM_DEVICECHANGE:
|
||||
// Get size of the root HWND
|
||||
GetWindowRect(GetDesktopWindow(), &rcRoot);
|
||||
SetWindowPos(hWndDesktop, HWND_BOTTOM,
|
||||
rcRoot.left, rcRoot.top, rcRoot.right - rcRoot.left, rcRoot.bottom - rcRoot.top,
|
||||
SWP_NOACTIVATE);
|
||||
//if (hWndListView)
|
||||
// SetWindowPos(hWndListView, hWndDesktop,
|
||||
// rcRoot.left, rcRoot.top, rcRoot.right - rcRoot.left, rcRoot.bottom - rcRoot.top,
|
||||
// SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
break;
|
||||
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
case WM_SYSCOMMAND:
|
||||
case WM_COMMAND:
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
case WM_CLOSE:
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CreateListView -
|
||||
Creates the Desktop's ListView.
|
||||
RETURNS -
|
||||
HWND to the listview if successfull,
|
||||
NULL otherwise.
|
||||
\* * * */
|
||||
HWND CreateListView(HWND hWndParent, RECT rc)
|
||||
{
|
||||
HWND hWndListView;
|
||||
LVITEM lviTestItem;
|
||||
WCHAR szTestItem[] = L"Test Item";
|
||||
|
||||
// Create the ListView
|
||||
hWndListView = CreateWindowEx(WS_EX_LEFT, WC_LISTVIEW, L"",
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
|
||||
LVS_ICON | LVS_SINGLESEL,
|
||||
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||||
hWndParent, (HMENU)ID_LISTVIEW, hAppInstance,
|
||||
NULL);
|
||||
|
||||
if(hWndListView == NULL)
|
||||
return NULL;
|
||||
|
||||
ListView_SetBkColor(hWndListView, CLR_NONE);
|
||||
|
||||
lviTestItem.mask = LVIF_STATE | LVIF_TEXT;
|
||||
lviTestItem.iItem = 0;
|
||||
lviTestItem.iSubItem = 0;
|
||||
lviTestItem.state = 0;
|
||||
lviTestItem.stateMask = 0;
|
||||
lviTestItem.pszText = (LPWSTR)&szTestItem;
|
||||
lviTestItem.cchTextMax = MAXTITLELEN;
|
||||
// lviTestItem.iImage = 1;
|
||||
|
||||
ListView_InsertItem(hWndListView, &lviTestItem);
|
||||
|
||||
return hWndListView;
|
||||
}
|
||||
492
progmgr/dialog.c
Normal file
@@ -0,0 +1,492 @@
|
||||
/* * * * * * * *\
|
||||
DIALOG.C -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's dialogs and related
|
||||
common functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <Commctrl.h>
|
||||
#include <Commdlg.h>
|
||||
#include <Shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <strsafe.h>
|
||||
#include "progmgr.h"
|
||||
#include "dialog.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
|
||||
/* Variables */
|
||||
WCHAR szDlgTitle[64];
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
NewGroupDlgProc -
|
||||
Dialog procedure for creating a group.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static GROUP grp = { 0 };
|
||||
BOOL bOKEnabled = FALSE;
|
||||
WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
HICON hIconDef = NULL;
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
// TODO:
|
||||
// Enable creation of common groups (enable the controls)
|
||||
// if permissions are available.
|
||||
// TODO:
|
||||
// fix minor GDI font/region leak
|
||||
|
||||
// Reset the necessary parts of the group structure
|
||||
grp.dwSignature = GRP_SIGNATURE;
|
||||
grp.wVersion = GRP_VERSION;
|
||||
grp.wChecksum = 0;
|
||||
grp.dwFlags = 0;
|
||||
grp.cItemArray = 0;
|
||||
// grp.pItemArray = 0; TODO: idk make sure this ain't all screwed up
|
||||
|
||||
// Set the window title
|
||||
LoadString(g_hAppInstance, IDS_DLT_GRP_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle));
|
||||
SetWindowText(hWndDlg, szDlgTitle);
|
||||
|
||||
// Populate the icon with the default path and index.
|
||||
GetModuleFileName(g_hAppInstance, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath));
|
||||
grp.iIconIndex = IDI_PROGGRP - 1;
|
||||
|
||||
// Get the default hIcon so we can delete it later
|
||||
hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0);
|
||||
|
||||
// Set the icon in the dialog
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
|
||||
// Set the maximum input length of the text boxes
|
||||
SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0);
|
||||
|
||||
// Disable the OK button since we're starting with no text in the box.
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
// Enable the common group checkbox if perms are good
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_COMMGROUP), g_bPermAdmin);
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if (LOWORD(wParam) == IDD_NAME)
|
||||
{
|
||||
// Name text control changed. See what's up...
|
||||
bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer));
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_CHICON:
|
||||
if (PickIconDlg(hWndDlg, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath), &grp.iIconIndex) == TRUE)
|
||||
{
|
||||
// Since we've got the new icon...
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_OK:
|
||||
// Check that all the applicable fields are filled out,
|
||||
// and if not then set the focus to the offending field
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_NAME));
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
if (bOKEnabled)
|
||||
{
|
||||
// Set the name of the group
|
||||
StringCchCopy(grp.szName, ARRAYSIZE(szBuffer), szBuffer);
|
||||
|
||||
// Set the flags of the group
|
||||
if (SendDlgItemMessage(hWndDlg, IDD_COMMGROUP, BM_GETCHECK, 0, 0) != BST_UNCHECKED)
|
||||
grp.dwFlags = grp.dwFlags || GRP_FLAG_COMMON;
|
||||
|
||||
// Set FILETIME
|
||||
GetSystemTimeAsFileTime(&grp.ftLastWrite);
|
||||
|
||||
// Set the rectangle of the group to be CW_USEDEFAULT
|
||||
grp.rcGroup.left = grp.rcGroup.top = grp.rcGroup.right = grp.rcGroup.bottom = CW_USEDEFAULT;
|
||||
|
||||
// Group's ready!
|
||||
if (CreateGroup(&grp) != NULL)
|
||||
{
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Failure!
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDef)
|
||||
DestroyIcon(hIconDef);
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
NewItemDlgProc -
|
||||
Dialog procedure for creating or modifying
|
||||
an item.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static ITEM itm = { 0 };
|
||||
BOOL bOKEnabled = FALSE;
|
||||
BOOL bWorkPath = FALSE;
|
||||
WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
WCHAR szPathBuffer[MAX_PATH] = { TEXT("\0") };
|
||||
HICON hIconDef = NULL;
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
// TODO:
|
||||
// require a valid group to be selected or else the dialog won't
|
||||
// EVEN BE AVAILABLE!!! or let you press ok.
|
||||
|
||||
// Reset the necessary parts of the item structure
|
||||
itm.dwFlags = 0;
|
||||
itm.uiHotkeyModifiers = 0;
|
||||
itm.uiHotkeyVirtualKey = 0;
|
||||
|
||||
// Set the window title
|
||||
LoadString(g_hAppInstance, IDS_DLT_ITEM_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle));
|
||||
SetWindowText(hWndDlg, szDlgTitle);
|
||||
|
||||
// Populate the icon with the default path and index.
|
||||
GetModuleFileName(NULL, (LPWSTR)&itm.szIconPath, MAX_PATH);
|
||||
itm.iIconIndex = IDI_PROGITM - 1;
|
||||
|
||||
// Get the default hIcon so we can delete it later
|
||||
hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0);
|
||||
|
||||
// Set the icon in the dialog
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
|
||||
// Set the maximum input length of the text boxes
|
||||
SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0);
|
||||
SendDlgItemMessage(hWndDlg, IDD_PATH, EM_LIMITTEXT, MAX_PATH, 0);
|
||||
SendDlgItemMessage(hWndDlg, IDD_WORKPATH, EM_LIMITTEXT, MAX_PATH, 0);
|
||||
|
||||
// Disable the OK button since we're starting with no text in the box.
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if ((LOWORD(wParam) == IDD_NAME) || (LOWORD(wParam) == IDD_PATH) || (LOWORD(wParam) == IDD_WORKPATH))
|
||||
{
|
||||
// A control has changed. See what's up...
|
||||
bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer));
|
||||
bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
if (bWorkPath)
|
||||
bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
// Check that we have selected an MDI child window as well
|
||||
if ((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, FALSE) == (HWND)NULL)
|
||||
bOKEnabled = FALSE;
|
||||
|
||||
// Enable or disable the relevant controls based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_BROWSE:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
LPVOID lpData;
|
||||
DWORD dwVerBuffer = 0;
|
||||
UINT uiTitleLen = MAX_TITLE_LENGTH;
|
||||
WCHAR szNameBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
WCHAR szFileBuffer[MAX_PATH] = { TEXT("\0") };
|
||||
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer, ARRAYSIZE(szFileBuffer));
|
||||
|
||||
// Initialize the structure
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWndDlg;
|
||||
ofn.lpstrFilter = TEXT("Programs\0*.exe;*.bat;*.com;*.cmd;*.lnk\0All Files (*.*)\0*.*\0");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = (LPWSTR)&szFileBuffer;
|
||||
// ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = ARRAYSIZE(szFileBuffer);
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = NULL;
|
||||
ofn.Flags = OFN_FILEMUSTEXIST;
|
||||
|
||||
if (GetOpenFileName(&ofn) == TRUE)
|
||||
SetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer);
|
||||
else
|
||||
break;
|
||||
|
||||
// copy the filename to a new buffer for later
|
||||
StringCchCopy(szNameBuffer, ARRAYSIZE(szNameBuffer), szFileBuffer);
|
||||
|
||||
// let's retrieve the application's friendly name too
|
||||
dwVerBuffer = GetFileVersionInfoSize((LPCWSTR)szFileBuffer, NULL);
|
||||
// if (dwVerBuffer != 0)
|
||||
if (NULL)
|
||||
{
|
||||
lpData = malloc(dwVerBuffer);
|
||||
// TODO: totally redo this it doesn't work
|
||||
|
||||
if (lpData != NULL)
|
||||
GetFileVersionInfo((LPCWSTR)szFileBuffer, (DWORD)0, dwVerBuffer, lpData);
|
||||
else
|
||||
break;
|
||||
|
||||
// TODO: this is hardcoded to english. make it dynamic later
|
||||
// TODO: this is so busted lol, really make it dynamic so it works
|
||||
VerQueryValue(lpData,
|
||||
TEXT("\\StringFileInfo\\040904b0\\FileDescription"),
|
||||
(LPVOID)&szNameBuffer, &uiTitleLen); // == 0
|
||||
|
||||
if (lpData)
|
||||
free(lpData);
|
||||
}
|
||||
else
|
||||
{
|
||||
PathStripPath((LPWSTR)&szNameBuffer);
|
||||
PathRemoveExtension((LPWSTR)&szNameBuffer);
|
||||
}
|
||||
|
||||
SetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)szNameBuffer);
|
||||
|
||||
// let's get the icon now
|
||||
if (ExtractIcon(g_hAppInstance, (LPWSTR)szFileBuffer, -1) > 0)
|
||||
{
|
||||
// file contains at least one icon, set the itm struct values
|
||||
StringCchCopy(itm.szIconPath, ARRAYSIZE(itm.szIconPath), szFileBuffer);
|
||||
itm.iIconIndex = 0;
|
||||
|
||||
// update icon
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IDD_BROWSE2:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
||||
GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
// Initialize the structure
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWndDlg;
|
||||
ofn.lpstrFilter = TEXT("Folders\0");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = (LPWSTR)&szPathBuffer;
|
||||
// ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = ARRAYSIZE(szPathBuffer);
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = NULL;
|
||||
ofn.Flags = OFN_FILEMUSTEXIST;
|
||||
|
||||
if (GetOpenFileName(&ofn) == TRUE) {
|
||||
SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case IDD_CHICON:
|
||||
if (PickIconDlg(hWndDlg, (LPWSTR)&itm.szIconPath, ARRAYSIZE(itm.szIconPath), &itm.iIconIndex) == TRUE)
|
||||
{
|
||||
// Since we've got the new icon...
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_WORKDIR:
|
||||
bWorkPath = IsDlgButtonChecked(hWndDlg, IDD_WORKDIR);
|
||||
|
||||
if (bWorkPath)
|
||||
{
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
PathRemoveFileSpec((LPWSTR)&szPathBuffer);
|
||||
SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowText(GetDlgItem(hWndDlg, IDD_WORKPATH), 0);
|
||||
}
|
||||
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_STAT_WORKDIR), bWorkPath);
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_WORKPATH), bWorkPath);
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_BROWSE2), bWorkPath);
|
||||
|
||||
break;
|
||||
|
||||
case IDD_OK:
|
||||
// Check that all the applicable fields are filled out,
|
||||
// and if not then set the focus to the offending field
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_NAME));
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_PATH));
|
||||
if (bWorkPath)
|
||||
{
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_WORKPATH));
|
||||
}
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
if (bOKEnabled)
|
||||
{
|
||||
// Set the name of the item
|
||||
StringCchCopy(itm.szName, ARRAYSIZE(szBuffer), szBuffer);
|
||||
|
||||
// And the paths...
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
StringCchCopy(itm.szExecPath, ARRAYSIZE(szPathBuffer), szPathBuffer);
|
||||
GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
StringCchCopy(itm.szWorkPath, ARRAYSIZE(szPathBuffer), szPathBuffer);
|
||||
|
||||
// Item's ready!
|
||||
if (CreateItem((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, 0), &itm) != NULL)
|
||||
{
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Failure!
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDef)
|
||||
DestroyIcon(hIconDef);
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
ShutdownDlgProc -
|
||||
Dialog procedure for powering off the computer.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_OK:
|
||||
{
|
||||
}
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
17
progmgr/dialog.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* * * * * * * *\
|
||||
DIALOG.H -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Dialog function prototypes and related
|
||||
common dialog functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Function Prototypes */
|
||||
BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
742
progmgr/group.c
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
GROUP.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Group window and program group/item functions.
|
||||
LICENSE INFORMATION -
|
||||
@@ -8,18 +8,564 @@
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <uxtheme.h>
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
// #define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
/* Variables */
|
||||
WNDCLASSEX wcGrp;
|
||||
WCHAR szGrpClass[16];
|
||||
HWND hWndMDIClient = NULL;
|
||||
HWND hWndFoundGroup = NULL;
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
InitializeGroups -
|
||||
Create the MDI Client window and initialize
|
||||
the group window class.
|
||||
RETURNS -
|
||||
TRUE if groups are successfully created.
|
||||
FALSE if otherwise.
|
||||
\* * * */
|
||||
BOOL InitializeGroups(VOID)
|
||||
{
|
||||
CLIENTCREATESTRUCT ccs = { 0 };
|
||||
WNDCLASSEX wce = { 0 };
|
||||
RECT rcFrame;
|
||||
|
||||
// Create the MDI Client Window
|
||||
ccs.hWindowMenu = GetSubMenu(GetMenu(g_hWndProgMgr), 2);
|
||||
ccs.idFirstChild = IDM_WINDOW_CHILDSTART;
|
||||
|
||||
GetClientRect(g_hWndProgMgr, &rcFrame);
|
||||
|
||||
if ((hWndMDIClient = CreateWindowEx(WS_EX_COMPOSITED,
|
||||
TEXT("MDIClient"), NULL, WS_CLIPCHILDREN | WS_CHILD |
|
||||
WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
|
||||
rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom,
|
||||
g_hWndProgMgr, (HMENU)1, g_hAppInstance, (LPWSTR)&ccs)) == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Load the group class string
|
||||
LoadString(g_hAppInstance, IDS_GRPCLASS,
|
||||
szGrpClass, ARRAYSIZE(szGrpClass));
|
||||
|
||||
// Register the group window class
|
||||
wce.cbSize = sizeof(WNDCLASSEX);
|
||||
wce.style = CS_DBLCLKS;
|
||||
wce.lpfnWndProc = GroupWndProc;
|
||||
wce.cbClsExtra = 0;
|
||||
wce.cbWndExtra = 0;
|
||||
wce.hInstance = g_hAppInstance;
|
||||
wce.hIcon = g_hGroupIcon = LoadImage(g_hAppInstance,
|
||||
MAKEINTRESOURCE(IDI_PROGGRP), IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
wce.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wce.lpszMenuName = NULL;
|
||||
wce.lpszClassName = szGrpClass;
|
||||
|
||||
if (!RegisterClassEx(&wce))
|
||||
return FALSE;
|
||||
|
||||
// Now we can create the groups
|
||||
if(LoadConfig(FALSE, FALSE, TRUE) != RCE_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
// TODO: if loading groups fails, throw an error
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CreateGroup -
|
||||
Create an MDI window from a group structure
|
||||
RETURNS -
|
||||
Handle to the new group window
|
||||
or NULL on failure
|
||||
\* * * */
|
||||
HWND CreateGroup(_In_ PGROUP pg)
|
||||
{
|
||||
MDICREATESTRUCT mcs = { NULL };
|
||||
PGROUP pGroup = NULL;
|
||||
HICON hIconLarge = NULL;
|
||||
HICON hIconSmall = NULL;
|
||||
HICON hIconTemp = NULL;
|
||||
HWND hWndGroup = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
RECT rcGroupWindow = { 0 };
|
||||
LVCOLUMN lvc = { 0 };
|
||||
|
||||
if (pg == NULL)
|
||||
return NULL;
|
||||
|
||||
// error checking, if we get trash don't try to
|
||||
// make a group out of it
|
||||
// TODO: if a group is garbled, throw an error
|
||||
// and ask the user if they want to delete it!
|
||||
if (pg->dwSignature != GRP_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
// allocate memory for a new group
|
||||
pGroup = (PGROUP)malloc(CalculateGroupMemory(pg, 1, 0));
|
||||
if (pGroup == NULL)
|
||||
return NULL;
|
||||
|
||||
// clean up the memory if it's valid
|
||||
ZeroMemory(pGroup, sizeof(*pGroup));
|
||||
|
||||
// copy over the group structure
|
||||
*pGroup = *pg;
|
||||
|
||||
// TODO: get group minimized/maximized flags
|
||||
|
||||
mcs.szClass = szGrpClass;
|
||||
mcs.szTitle = pg->szName;
|
||||
mcs.hOwner = g_hAppInstance;
|
||||
if ((pg->rcGroup.left == CW_USEDEFAULT) & (pg->rcGroup.right == CW_USEDEFAULT))
|
||||
{
|
||||
mcs.x = mcs.y = mcs.cx = mcs.cy = CW_USEDEFAULT;
|
||||
}
|
||||
mcs.style = WS_VISIBLE | WS_THICKFRAME | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
|
||||
// TODO: should I pass the pointer to the group through here
|
||||
// or is it better and easier to just do it with GWLP_USERDATA?
|
||||
mcs.lParam = (LPARAM)NULL;
|
||||
|
||||
if ((hWndGroup = (HWND)SendMessage(hWndMDIClient, WM_MDICREATE, 0,
|
||||
(LPARAM)(LPTSTR)&mcs)) == NULL)
|
||||
return NULL;
|
||||
|
||||
// Associate the group structure pointer to the group window
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
|
||||
// Resize the group
|
||||
if (pg->wp.length == sizeof(WINDOWPLACEMENT))
|
||||
SetWindowPlacement(hWndGroup, &pg->wp);
|
||||
|
||||
// Load the group icon
|
||||
if (ExtractIconEx(pg->szIconPath, pg->iIconIndex, &hIconLarge, &hIconSmall, 1))
|
||||
{
|
||||
if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON,
|
||||
ICON_SMALL, (LPARAM)hIconSmall))
|
||||
DestroyIcon(hIconTemp);
|
||||
if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON,
|
||||
ICON_BIG, (LPARAM)hIconLarge))
|
||||
DestroyIcon(hIconTemp);
|
||||
}
|
||||
|
||||
// Get the group window rect
|
||||
GetClientRect(hWndGroup, &rcGroupWindow);
|
||||
|
||||
// Create the group window ListView control
|
||||
if ((hWndListView = CreateWindowEx(WS_EX_LEFT, WC_LISTVIEW,
|
||||
TEXT("ListView"),
|
||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
|
||||
LVS_ICON | LVS_SINGLESEL | LVS_AUTOARRANGE,
|
||||
mcs.x, mcs.y, mcs.cx, mcs.cy,
|
||||
hWndGroup, NULL, g_hAppInstance, NULL)) == NULL)
|
||||
return NULL;
|
||||
|
||||
// ((LVS_AUTOARRANGE & bAutoArrange) * LVS_AUTOARRANGE)
|
||||
|
||||
// Resize it to fit the window
|
||||
SetWindowPos(hWndListView, NULL,
|
||||
rcGroupWindow.left, rcGroupWindow.top,
|
||||
rcGroupWindow.right - rcGroupWindow.left,
|
||||
rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER);
|
||||
|
||||
// Add the explorer style because it looks good
|
||||
SetWindowTheme(hWndListView, TEXT("Explorer"), NULL);
|
||||
|
||||
// Get this bad boy an image list
|
||||
// TODO: if cxicon/cyicon change make sure we handle that
|
||||
// don't require a program restart, DPI!!!
|
||||
hImageList = ImageList_Create(GetSystemMetrics(SM_CXICON),
|
||||
GetSystemMetrics(SM_CYICON), ILC_COLOR32, 0, 1);
|
||||
ListView_SetImageList(hWndListView, hImageList, LVSIL_NORMAL);
|
||||
|
||||
// since the list is viewing we can load items if applicable
|
||||
if (pGroup->cItemArray > 0)
|
||||
LoadItems(hWndGroup);
|
||||
|
||||
// TODO: make sure the groups delete their icons upon destruction!
|
||||
// AND IMAGE LIST!!!!!!!!? i think it's nuked w/ listview though
|
||||
return hWndGroup;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RemoveGroup -
|
||||
Removes and cleans up a group window
|
||||
RETURNS -
|
||||
TRUE if cleanup is successful,
|
||||
FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL RemoveGroup(_In_ HWND hWndGroup, _In_ BOOL bEliminate)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
BOOL bReturn = TRUE;
|
||||
|
||||
// TODO: do i have to delete the titlebar icons?
|
||||
|
||||
if (bEliminate == TRUE)
|
||||
{
|
||||
// TODO: remove group from registry
|
||||
// if successful blah blah blah
|
||||
bEliminate = TRUE;
|
||||
}
|
||||
|
||||
// get the group struct pointer
|
||||
if ((pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA)) == NULL)
|
||||
bReturn = FALSE;
|
||||
else
|
||||
free(pGroup);
|
||||
|
||||
// close the group window
|
||||
SendMessage(hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndGroup, 0);
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CreateItem -
|
||||
Creates a new program item
|
||||
RETURNS -
|
||||
Pointer to the item if successful
|
||||
NULL otherwise
|
||||
\* * * */
|
||||
PITEM CreateItem(_In_ HWND hWndGroup, _In_ PITEM pi)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
PGROUP pNewGroup = NULL;
|
||||
PITEM pItem = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
HICON hIcon = NULL;
|
||||
LVITEM lvi = { 0 };
|
||||
|
||||
// we actually just want the group pointer lol
|
||||
pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA);
|
||||
|
||||
// return NULL if we can't get to the group or item
|
||||
if (hWndGroup == NULL)
|
||||
return NULL;
|
||||
if (pGroup == NULL)
|
||||
return NULL;
|
||||
if (pi == NULL)
|
||||
return NULL;
|
||||
|
||||
// get the listview window
|
||||
hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
return NULL;
|
||||
|
||||
// if we reallocate memory then send the new pointer in
|
||||
pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 1, 0));
|
||||
if (pNewGroup != NULL)
|
||||
{
|
||||
pGroup = pNewGroup;
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
}
|
||||
|
||||
// add the item
|
||||
pItem = pGroup->pItemArray + pGroup->cItemArray;
|
||||
*pItem = *pi;
|
||||
|
||||
// increment the item counter
|
||||
pGroup->cItemArray++;
|
||||
|
||||
// then get the pointer to the group's image list
|
||||
hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL);
|
||||
|
||||
// extract that icon son!!
|
||||
hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex);
|
||||
|
||||
// populate the listview with the relevant information
|
||||
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
lvi.iItem = pGroup->cItemArray;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = pItem->szName;
|
||||
lvi.cchTextMax = ARRAYSIZE(pItem->szName);
|
||||
lvi.iImage = ImageList_AddIcon(hImageList, hIcon);
|
||||
lvi.lParam = (LPARAM)pItem;
|
||||
|
||||
// copy that bad boy into the listview
|
||||
ListView_InsertItem(hWndListView, &lvi);
|
||||
|
||||
// get that hicon outta here
|
||||
DestroyIcon(hIcon);
|
||||
|
||||
// this is all terrible i'm gonna rewrite this whole file
|
||||
// why is the listview even touched here just... omg...
|
||||
// BAD!! bad functions
|
||||
|
||||
// TODO: fail if the listview item isn't added
|
||||
return pItem;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
LoadItems -
|
||||
Loads all of the items in a group structure
|
||||
RETURNS -
|
||||
TRUE if successful
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL LoadItems(_In_ HWND hWndGroup)
|
||||
{
|
||||
PGROUP pGroup = NULL;
|
||||
PGROUP pNewGroup = NULL;
|
||||
PITEM pItem = NULL;
|
||||
HWND hWndListView = NULL;
|
||||
HIMAGELIST hImageList = NULL;
|
||||
LVITEM lvi = { 0 };
|
||||
UINT cItemIndex = 0;
|
||||
HICON hIcon = NULL;
|
||||
|
||||
// return NULL if we can't get to the group
|
||||
if (hWndGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
// retrieve the group pointer
|
||||
pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA);
|
||||
if (pGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
// get the listview window
|
||||
hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
return FALSE;
|
||||
|
||||
// make sure we have enough memory for the items
|
||||
pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 0, 1));
|
||||
if (pNewGroup != NULL)
|
||||
{
|
||||
pGroup = pNewGroup;
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
}
|
||||
|
||||
// then get the pointer to the group's image list
|
||||
hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL);
|
||||
|
||||
while (pGroup->cItemArray > cItemIndex)
|
||||
{
|
||||
pItem = pGroup->pItemArray + cItemIndex;
|
||||
|
||||
// extract that icon son!!
|
||||
hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex);
|
||||
|
||||
// populate the listview with the relevant information
|
||||
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
||||
lvi.iItem = cItemIndex;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = pItem->szName;
|
||||
lvi.cchTextMax = ARRAYSIZE(pItem->szName);
|
||||
lvi.iImage = ImageList_AddIcon(hImageList, hIcon);
|
||||
lvi.lParam = (LPARAM)pItem;
|
||||
|
||||
// copy that bad boy into the listview
|
||||
ListView_InsertItem(hWndListView, &lvi);
|
||||
|
||||
cItemIndex++;
|
||||
}
|
||||
|
||||
if (hIcon)
|
||||
// get that hicon outta here
|
||||
DestroyIcon(hIcon);
|
||||
|
||||
// TODO: fail if the listview item isn't added
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RemoveItem -
|
||||
Removes a program item
|
||||
RETURNS -
|
||||
TRUE if item was successfully removed
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL RemoveItem(_In_ PITEM pi)
|
||||
{
|
||||
// TODO: implement this
|
||||
// return NULL if we can't get to the group
|
||||
if (pi == NULL)
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
ExecuteItem -
|
||||
Runs a program item
|
||||
RETURNS -
|
||||
TRUE if item was successfully ran
|
||||
FALSE otherwise
|
||||
\* * * */
|
||||
BOOL ExecuteItem(_In_ PITEM pi)
|
||||
{
|
||||
// TODO: nCmdShow from program item flags
|
||||
ShellExecute(g_hWndProgMgr, TEXT("open"),
|
||||
pi->szExecPath, NULL,
|
||||
(pi->szWorkPath != TEXT("")) ? pi->szWorkPath : NULL,
|
||||
SW_NORMAL);
|
||||
|
||||
// TODO: if item has run as admin as a flag,
|
||||
// run it as an admin
|
||||
|
||||
// TODO: if path is invalid or other error then tell the user
|
||||
|
||||
// TODO: make sure environment is
|
||||
// refreshed before execution
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
UpdateGroup -
|
||||
Updates group information to prepare
|
||||
it for being saved.
|
||||
ABSTRACT -
|
||||
This function will update all of the
|
||||
relevant structures in a group struct
|
||||
in preparation for saving the group.
|
||||
RETURNS -
|
||||
Nothing.
|
||||
\* * * */
|
||||
VOID UpdateGroup(_In_ PGROUP pg)
|
||||
{
|
||||
DWORD dwFlags = 0;
|
||||
HWND hWndGroup = NULL;
|
||||
|
||||
// Set the important flags
|
||||
pg->dwSignature = GRP_SIGNATURE;
|
||||
pg->wVersion = GRP_VERSION;
|
||||
|
||||
// Set the group checksum
|
||||
pg->wChecksum = 1; // NOTE: implement this for real later lol
|
||||
|
||||
// TODO: group flags
|
||||
// pg->dwFlags = GRP_FLAG_MAXIMIZED;// GetGroupFlags(pgw);
|
||||
|
||||
// Set FILETIME
|
||||
GetSystemTimeAsFileTime(&pg->ftLastWrite);
|
||||
|
||||
if (hWndGroup = GetHwndFromPGroup(pg))
|
||||
{
|
||||
// Get the group window rect and name
|
||||
pg->wp.length = sizeof(WINDOWPLACEMENT);
|
||||
GetWindowPlacement(hWndGroup, &pg->wp);
|
||||
GetWindowText(hWndGroup, pg->szName, ARRAYSIZE(pg->szName));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GetHwndFromPGroup -
|
||||
In goes a PGROUP out comes a HWND
|
||||
RETURNS -
|
||||
HWND.
|
||||
\* * * */
|
||||
HWND GetHwndFromPGroup(_In_ PGROUP pg)
|
||||
{
|
||||
EnumChildWindows(g_hWndProgMgr, (WNDENUMPROC)GetHwndFromPGroupEnum, (LPARAM)pg);
|
||||
|
||||
return hWndFoundGroup;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GetHwndFromPGroupEnum -
|
||||
Enum Function
|
||||
RETURNS -
|
||||
HWND.
|
||||
\* * * */
|
||||
BOOL GetHwndFromPGroupEnum(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
{
|
||||
if (lParam == GetWindowLongPtr(hwnd, GWLP_USERDATA))
|
||||
{
|
||||
hWndFoundGroup = hwnd;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hWndFoundGroup = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
VerifyGroup -
|
||||
Verifies that a group contains the
|
||||
correct information about itself.
|
||||
ABSTRACT -
|
||||
This function will check the checksum,
|
||||
verify the number of items, check other
|
||||
parts of the strucutre. If requested,
|
||||
it will repair the group if it is damaged.
|
||||
RETURNS -
|
||||
TRUE if group appears to be fine
|
||||
FALSE if the group is damaged
|
||||
\* * * */
|
||||
BOOL VerifyGroup(_In_ PGROUP pg, _In_ BOOL bRepair)
|
||||
{
|
||||
if (pg->dwSignature != GRP_SIGNATURE)
|
||||
return FALSE;
|
||||
|
||||
// if (pg->wVersion != GRP_VERSION)
|
||||
// some sort of version difference handling
|
||||
|
||||
if (pg->wChecksum == 1234)
|
||||
// TODO: calculate checksum function
|
||||
return FALSE;
|
||||
|
||||
// TODO: use ftlastwrite to throw an error
|
||||
// if system clock is in the future
|
||||
|
||||
// calculate the size of the group based on item of numbers
|
||||
|
||||
// TODO: change to return a dword error value
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
CalculateGroupMemory -
|
||||
Calculates the memory needed by a group.
|
||||
Takes a group structure pointer and the
|
||||
number of desired items as input.
|
||||
RETURNS -
|
||||
Size in bytes that a group should take up.
|
||||
\* * * */
|
||||
UINT CalculateGroupMemory(_In_ PGROUP pGroup, _In_ UINT cItems, _In_ BOOL bLean)
|
||||
{
|
||||
UINT cbGroupSize = 0;
|
||||
UINT cItemBlock = 0;
|
||||
|
||||
// first add the size of a group strucutre
|
||||
cbGroupSize += sizeof(GROUP);
|
||||
|
||||
// calculate the total amount of items wanted
|
||||
cItemBlock = pGroup->cItemArray + cItems;
|
||||
|
||||
if (!bLean)
|
||||
// round the amount of items to the nearest but highest ITEM_BATCH_COUNT
|
||||
cItemBlock = ((cItemBlock + ITEM_BATCH_COUNT) / ITEM_BATCH_COUNT) * ITEM_BATCH_COUNT;
|
||||
|
||||
// finally calculate the total group size
|
||||
cbGroupSize += cItemBlock * sizeof(ITEM);
|
||||
|
||||
return cbGroupSize;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
GroupWndProc -
|
||||
Group window procedure.
|
||||
@@ -28,49 +574,181 @@ WNDCLASSEX wcGrp;
|
||||
\* * * */
|
||||
LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
|
||||
case WM_CREATE:
|
||||
{
|
||||
CREATESTRUCT* pCreateStruct;
|
||||
MDICREATESTRUCT* pMDICreateStruct;
|
||||
|
||||
// code borrowed from winprog
|
||||
pCreateStruct = (CREATESTRUCT*)lParam;
|
||||
pMDICreateStruct = (MDICREATESTRUCT*)pCreateStruct->lpCreateParams;
|
||||
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
if (CmdProc(hWnd, wParam, lParam))
|
||||
return 0;
|
||||
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
case WM_CONTEXTMENU:
|
||||
{
|
||||
POINT pt = { 0 };
|
||||
HMENU hMenu = NULL;
|
||||
BOOL bPopup = FALSE;
|
||||
|
||||
// LVHT_ONITEM
|
||||
// LVHT_NOWHERE
|
||||
|
||||
pt.x = GET_X_LPARAM(lParam);
|
||||
pt.y = GET_Y_LPARAM(lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
return ShowWindow(hWnd, SW_MINIMIZE);
|
||||
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
|
||||
HWND hWndListView = NULL;
|
||||
|
||||
// find the listview control
|
||||
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
break;
|
||||
|
||||
switch (lpnmhdr->code)
|
||||
{
|
||||
|
||||
case NM_DBLCLK:
|
||||
{
|
||||
LVITEM lvi = { 0 };
|
||||
PITEM pItem = NULL;
|
||||
|
||||
// what info do we want?
|
||||
lvi.mask = LVIF_PARAM;
|
||||
lvi.iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
|
||||
|
||||
// get the listview item
|
||||
ListView_GetItem(hWndListView, &lvi);
|
||||
|
||||
// get the item pointer
|
||||
pItem = (PITEM)lvi.lParam;
|
||||
|
||||
// verify...
|
||||
if (pItem)
|
||||
{
|
||||
// and execute!
|
||||
ExecuteItem(pItem);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// GroupProcDefault:
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
HWND hWndListView = NULL;
|
||||
RECT rcGroupWindow = { 0 };
|
||||
|
||||
// get the group window rect
|
||||
GetClientRect(hWnd, &rcGroupWindow);
|
||||
|
||||
// find the listview control
|
||||
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
break;
|
||||
|
||||
// resize it to fit the window
|
||||
SetWindowPos(hWndListView, NULL,
|
||||
rcGroupWindow.left, rcGroupWindow.top,
|
||||
rcGroupWindow.right - rcGroupWindow.left,
|
||||
rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER);
|
||||
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
default:
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return DefMDIChildProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
InitGroups -
|
||||
Initialize variables for the betterment of groups forever
|
||||
Make great glorious MDI Client
|
||||
GroupCmdProc -
|
||||
Group syscommand procedure.
|
||||
RETURNS -
|
||||
Zero if nothing, otherwise returns the good stuff.
|
||||
\* * * */
|
||||
|
||||
/* * * *\
|
||||
TempCreateGroup -
|
||||
th
|
||||
RETURNS -
|
||||
handle to window
|
||||
\* * * */
|
||||
HWND TempCreateGroup(HWND hMDIClient)
|
||||
LRESULT CALLBACK GroupCmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
MDICREATESTRUCT mcs;
|
||||
HWND hChild;
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
case IDM_FILE_OPEN:
|
||||
{
|
||||
HWND hWndListView = NULL;
|
||||
LVITEM lvi = { 0 };
|
||||
PITEM pItem = NULL;
|
||||
|
||||
mcs.szClass = szGrpClass;
|
||||
mcs.szTitle = L"";
|
||||
mcs.hOwner = hAppInstance;
|
||||
mcs.x = mcs.y = mcs.cx = mcs.cy = CW_USEDEFAULT;
|
||||
mcs.style = WS_VISIBLE;
|
||||
// find the listview control
|
||||
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
|
||||
if (hWndListView == NULL)
|
||||
break;
|
||||
|
||||
hChild = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LPARAM)(LPTSTR)&mcs);
|
||||
// if (!hChild)
|
||||
// {
|
||||
// MessageBox(hMDIClient, L"MDI Child creation failed.", L"Oh Oh...",
|
||||
// MB_ICONEXCLAMATION | MB_OK);
|
||||
// }
|
||||
return hChild;
|
||||
// what info do we want?
|
||||
lvi.mask = LVIF_PARAM;
|
||||
lvi.iItem = ((LPNMITEMACTIVATE)lParam)->iItem;
|
||||
|
||||
// get the listview item
|
||||
ListView_GetItem(hWndListView, &lvi);
|
||||
|
||||
// get the item pointer
|
||||
pItem = (PITEM)lvi.lParam;
|
||||
|
||||
// verify...
|
||||
if (pItem)
|
||||
{
|
||||
// and execute!
|
||||
ExecuteItem(pItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case IDM_FILE_MOVE:
|
||||
// TODO: ITEM Create dialog with other MDI groups, pick one to move item
|
||||
break;
|
||||
|
||||
case IDM_FILE_COPY:
|
||||
// TODO: ITEM Copy item structure to clipboard
|
||||
break;
|
||||
|
||||
case IDM_FILE_DELETE:
|
||||
// TODO: ITEM/GROUP Delete selected item, if no items selected or no items
|
||||
// exist then delete the group
|
||||
break;
|
||||
|
||||
case IDM_FILE_PROPS:
|
||||
// TODO: ITEM/GROUP Open properties of selected item or if nothing selected
|
||||
// then open group properties
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
GROUP.H -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program group/item structures, functions and definitons
|
||||
LICENSE INFORMATION -
|
||||
@@ -10,32 +10,39 @@
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Includes */
|
||||
#include <wtypes.h>
|
||||
|
||||
/* Definitions */
|
||||
#define MAX_GROUPS 512
|
||||
#define MAX_ITEMS 512
|
||||
#define MAX_TITLE_LENGTH MAX_PATH
|
||||
#define MAX_TITLE_LENGTH 255 // Same as the registry key name max length
|
||||
#define ITEM_BATCH_COUNT 8
|
||||
// Group Format Definitions
|
||||
#define GRP_SIGNATURE 0x47324D50L // PM2G
|
||||
#define GRP_VERSION 2 // Increment for breaking changes, format version
|
||||
// Group Flag Values (DWORD)
|
||||
#define GRP_FLAG_COMMON 0x00000001
|
||||
#define GRP_FLAG_READONLY 0x00000002
|
||||
#define GRP_FLAG_MINIMIZED 0x00000004
|
||||
#define GRP_FLAG_MAXIMIZED 0x00000008
|
||||
// Item Flag Values (DWORD)
|
||||
#define ITM_FLAG_HOTKEY 0x00000001
|
||||
#define ITM_FLAG_PRIVILEGE 0x00000002
|
||||
#define ITM_FLAG_MINIMIZED 0x00000004
|
||||
#define ITM_FLAG_MAXIMIZED 0x00000008
|
||||
|
||||
/* Structures */
|
||||
// Item Structure
|
||||
typedef struct _ITEM {
|
||||
// Item executable and name
|
||||
WCHAR szItemName[MAX_TITLE_LENGTH];
|
||||
WCHAR szExecPath[MAX_PATH]; // Path of the item executable
|
||||
WCHAR szName[MAX_TITLE_LENGTH];
|
||||
WCHAR szExecPath[MAX_PATH]; // Path of the executable
|
||||
WCHAR szWorkPath[MAX_PATH]; // Working directory
|
||||
|
||||
// Item flags
|
||||
DWORD dwFlags; // Use with ITM_FLAG_* values.
|
||||
UINT uiHotkeyModifiers;
|
||||
UINT uiHotkeyVirtualKey;
|
||||
// Icon
|
||||
WCHAR szIconPath[MAX_PATH]; // Path of the icon
|
||||
UINT uiIconIndex; // Index of the icon
|
||||
WCHAR szIconPath[MAX_PATH];
|
||||
INT iIconIndex;
|
||||
} ITEM, * PITEM;
|
||||
|
||||
// Group format, .GRP
|
||||
@@ -44,27 +51,43 @@ typedef struct _GROUP {
|
||||
DWORD dwSignature; // Set to GRP_SIGNATURE
|
||||
WORD wVersion; // Group format version
|
||||
WORD wChecksum;
|
||||
|
||||
// Group information
|
||||
WCHAR szGroupName[MAX_TITLE_LENGTH];
|
||||
WCHAR szName[MAX_TITLE_LENGTH];
|
||||
DWORD dwFlags; // Use with GRP_FLAG_* values.
|
||||
FILETIME ftLastWrite;
|
||||
|
||||
// Window information
|
||||
RECT rcGroup;
|
||||
WINDOWPLACEMENT wp;
|
||||
// Icon
|
||||
WCHAR szIconPath[MAX_PATH];
|
||||
INT iIconIndex;
|
||||
// Items
|
||||
WORD cItems; // Number of items
|
||||
PITEM iItems; // Array of items
|
||||
WORD cItemArray; // Number of items in pItemArray
|
||||
ITEM pItemArray[1]; // Array of items
|
||||
} GROUP, * PGROUP;
|
||||
|
||||
// Group window information
|
||||
typedef struct _GROUPWND {
|
||||
// Window information
|
||||
HWND hWndGroup;
|
||||
RECT rcGroup; // Window rectangle
|
||||
/* Global Variables */
|
||||
extern HWND hWndMDIClient;
|
||||
|
||||
// Group information
|
||||
HANDLE hGroup; // Handle to GROUP object
|
||||
} GROUPINFO, * PGROUPINFO;
|
||||
/* Local Variables */
|
||||
|
||||
/* Function Prototypes */
|
||||
BOOL InitializeGroups(VOID);
|
||||
// Group Management
|
||||
HWND CreateGroup(_In_ PGROUP pg);
|
||||
BOOL RemoveGroup(_In_ HWND hWndGroup, _In_ BOOL bEliminate);
|
||||
// Item Management
|
||||
PITEM CreateItem(_In_ HWND hWndGroup, _In_ PITEM pi);
|
||||
BOOL LoadItems(_In_ HWND hWndGroup);
|
||||
BOOL RemoveItem(_In_ PITEM pi);
|
||||
BOOL ExecuteItem(_In_ PITEM pi);
|
||||
// Save/Load helper functions
|
||||
VOID UpdateGroup(_In_ PGROUP pg);
|
||||
BOOL VerifyGroup(_In_ PGROUP pg, _In_ BOOL bRepair);
|
||||
// Helper functions
|
||||
UINT CalculateGroupMemory(_In_ PGROUP pGroup, _In_ UINT cItems, _In_ BOOL bLean);
|
||||
HWND GetHwndFromPGroup(_In_ PGROUP pg);
|
||||
BOOL GetHwndFromPGroupEnum(_In_ HWND hwnd, _In_ LPARAM lParam);
|
||||
// Group Window
|
||||
LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
HWND TempCreateGroup(HWND hMDIClient);
|
||||
LRESULT CALLBACK GroupCmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
38
progmgr/grpupdat.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* * * * * * * *\
|
||||
GRPUPDAT.H -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Header containing classic program group structures
|
||||
in order to facilitate conversion to the new format.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Includes */
|
||||
#include <wtypes.h>
|
||||
|
||||
/* Definitions */
|
||||
// Group signatures
|
||||
#define OLDGRP_SIGNATURE 0x43554D50L // PMUC
|
||||
|
||||
/* Structures */
|
||||
// Old group format, .GRP
|
||||
typedef struct _OLDGROUP {
|
||||
DWORD dwMagic; // Set to OLDGRP_SIGNATURE
|
||||
WORD wCheckSum; // Seemingly unused
|
||||
WORD cbGroup; // Size of group
|
||||
RECT rcNormal; // Window rect
|
||||
POINT ptMin; // Minimized window position
|
||||
WORD nCmdShow; // Min/max state
|
||||
WORD pName; // Group name
|
||||
WORD cxIcon; // Icon width
|
||||
WORD cyIcon; // Icon height
|
||||
WORD wIconFormat;
|
||||
WORD wReserved; // Unused
|
||||
|
||||
WORD cItems; // Number of items
|
||||
WORD rgiItems[1]; // Array of item offsets
|
||||
} OLDGROUP, * POLDGROUP;
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 766 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
progmgr/icons/progmgrd.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
BIN
progmgr/icons/src/progmgrd.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
progmgr/icons/src/progmgrd.pdn
Normal file
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
PROGMGR.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's main file, now with extra wWinMain!
|
||||
LICENSE INFORMATION -
|
||||
@@ -8,32 +8,57 @@
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define SECURITY_WIN32
|
||||
#include <Windows.h>
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
// #define WIN32_LEAN_AND_MEAN
|
||||
#define SECURITY_WIN32
|
||||
#include <Windows.h>
|
||||
|
||||
/* Variables */
|
||||
// Global
|
||||
BOOL bIsDefaultShell = FALSE;
|
||||
// Window Related
|
||||
HICON hProgMgrIcon = NULL;
|
||||
HICON hGroupIcon = NULL;
|
||||
HINSTANCE hAppInstance;
|
||||
HWND hWndProgMgr = NULL;
|
||||
HWND hWndMDIClient = NULL;
|
||||
#ifdef _DEBUG
|
||||
BOOL g_bIsDebugBuild = TRUE;
|
||||
#else
|
||||
BOOL g_bIsDebugBuild = FALSE;
|
||||
#endif
|
||||
BOOL g_bIsDefaultShell = FALSE;
|
||||
// Handles
|
||||
HINSTANCE g_hAppInstance;
|
||||
HWND g_hWndProgMgr = NULL;
|
||||
// Icons
|
||||
HICON g_hProgMgrIcon = NULL;
|
||||
HICON g_hGroupIcon = NULL;
|
||||
// Global Strings
|
||||
WCHAR szAppTitle[32];
|
||||
WCHAR szProgMgr[] = L"progmgr";
|
||||
WCHAR szWebsite[64];
|
||||
WCHAR szClass[16];
|
||||
WCHAR szGrpClass[16];
|
||||
WCHAR g_szAppTitle[64];
|
||||
WCHAR g_szProgMgr[] = TEXT("progmgr");
|
||||
WCHAR g_szWebsite[64];
|
||||
WCHAR g_szClass[16];
|
||||
// Permissions
|
||||
BOOL g_bPermAdmin; // Has Administrator permissions
|
||||
BOOL g_bPermGuest; // Has Guest permissions
|
||||
BOOL g_bPermPower; // Has power option permissions
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
UpdatePermissions -
|
||||
Update the permissions for the user based
|
||||
on account settings.
|
||||
RETURNS -
|
||||
TRUE if permissions are found successfully.
|
||||
FALSE if otherwise.
|
||||
\* * * */
|
||||
BOOL UpdatePermissions(VOID)
|
||||
{
|
||||
// SE_SHUTDOWN_NAME
|
||||
g_bPermAdmin = FALSE;
|
||||
g_bPermGuest = FALSE;
|
||||
g_bPermPower = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
wWinMain -
|
||||
Program Manager's entry point.
|
||||
@@ -44,66 +69,61 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||
HANDLE hAccel;
|
||||
HMENU hMenu;
|
||||
HMENU hSystemMenu;
|
||||
HWND hOldProgMgr;
|
||||
WNDCLASS wc = { 0 };
|
||||
WNDCLASSEX wce = { 0 };
|
||||
WCHAR szBuffer[MAX_PATH];
|
||||
RECT rcRoot;
|
||||
POINT ptOffset;
|
||||
POINT ptOffset = { 0 };
|
||||
|
||||
hAppInstance = hInstance;
|
||||
// Grab the instance
|
||||
g_hAppInstance = hInstance;
|
||||
|
||||
// Create Strings
|
||||
LoadString(hAppInstance, IDS_PMCLASS, szClass, ARRAYSIZE(szClass));
|
||||
LoadString(hAppInstance, IDS_GRPCLASS, szGrpClass, ARRAYSIZE(szGrpClass));
|
||||
LoadString(hAppInstance, IDS_APPTITLE, szAppTitle, ARRAYSIZE(szAppTitle));
|
||||
LoadString(hAppInstance, IDS_WEBSITE, szWebsite, ARRAYSIZE(szWebsite));
|
||||
LoadString(g_hAppInstance, IDS_PMCLASS, g_szClass, ARRAYSIZE(g_szClass));
|
||||
LoadString(g_hAppInstance, IDS_APPTITLE, g_szAppTitle, ARRAYSIZE(g_szAppTitle));
|
||||
LoadString(g_hAppInstance, IDS_WEBSITE, g_szWebsite, ARRAYSIZE(g_szWebsite));
|
||||
|
||||
// Lazily search for another instance of Program Manager
|
||||
// If we find one, switch focus to it and then abort.
|
||||
hOldProgMgr = FindWindowEx(NULL, NULL, g_szClass, NULL);
|
||||
|
||||
if (hOldProgMgr != NULL)
|
||||
{
|
||||
SwitchToThisWindow(hOldProgMgr, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get Desktop background color
|
||||
//CreateSolidBrush(GetBackgroundColor
|
||||
|
||||
// Register the Frame Window Class
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hAppInstance;
|
||||
wc.hIcon = hProgMgrIcon = LoadImage(hAppInstance, MAKEINTRESOURCE(IDI_PROGMGR), IMAGE_ICON,
|
||||
wc.hInstance = g_hAppInstance;
|
||||
wc.hIcon = g_hProgMgrIcon = LoadImage(g_hAppInstance, MAKEINTRESOURCE(IDI_PROGMGR), IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
// wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN);
|
||||
wc.lpszClassName = szClass;
|
||||
wc.lpszClassName = g_szClass;
|
||||
|
||||
if (!RegisterClass(&wc))
|
||||
return FALSE;
|
||||
|
||||
// Register the Group Window Class
|
||||
wce.cbSize = sizeof(WNDCLASSEX);
|
||||
wce.lpfnWndProc = GroupWndProc;
|
||||
wce.cbClsExtra = 0;
|
||||
wce.cbWndExtra = 0;
|
||||
wce.hInstance = hAppInstance;
|
||||
wce.hIcon = hGroupIcon = LoadImage(hAppInstance, MAKEINTRESOURCE(IDI_PROGGRP), IMAGE_ICON,
|
||||
0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||
wce.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wce.lpszMenuName = NULL;
|
||||
wce.lpszClassName = szGrpClass;
|
||||
if (!RegisterClassEx(&wce))
|
||||
return FALSE;
|
||||
|
||||
// Load the Accelerator table
|
||||
hAccel = LoadAccelerators(hAppInstance, MAKEINTRESOURCE(IDA_ACCELS));
|
||||
hAccel = LoadAccelerators(g_hAppInstance, MAKEINTRESOURCE(IDA_ACCELS));
|
||||
if (!hAccel)
|
||||
return FALSE;
|
||||
|
||||
// Perform Registry actions, close if registry is inaccessible.
|
||||
if (InitializeRegistryKeys())
|
||||
{
|
||||
bIsDefaultShell = IsProgMgrDefaultShell();
|
||||
LoadConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!InitializeRegistryKeys())
|
||||
return FALSE;
|
||||
|
||||
g_bIsDefaultShell = IsProgMgrDefaultShell();
|
||||
|
||||
// Load configuration, but don't load groups yet
|
||||
if(LoadConfig(TRUE, TRUE, FALSE) != RCE_SUCCESS)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get size of the root HWND
|
||||
GetWindowRect(GetDesktopWindow(), &rcRoot);
|
||||
@@ -113,23 +133,24 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||
SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, &ptOffset.y, 0);
|
||||
|
||||
// Create main window with a default size
|
||||
// NOTE: i pulled 320x240 out of my ass, make this dynamic later
|
||||
if (!CreateWindow(wc.lpszClassName, szAppTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
// TODO: i pulled 320x240 out of my ass, make this dynamic later
|
||||
if ((g_hWndProgMgr = CreateWindowW(wc.lpszClassName, g_szAppTitle,
|
||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
rcRoot.left + ptOffset.x, rcRoot.top + ptOffset.y,
|
||||
rcRoot.left + ptOffset.x + 320, rcRoot.top + ptOffset.y + 240,
|
||||
0, 0, hAppInstance, NULL))
|
||||
0, 0, g_hAppInstance, NULL)) == NULL)
|
||||
return 2;
|
||||
|
||||
// Set the window size from the registry, but only if the coords make sense
|
||||
if ((rcMainWindow.left != rcMainWindow.right) && (rcMainWindow.top != rcMainWindow.bottom))
|
||||
SetWindowPos(hWndProgMgr, NULL,
|
||||
SetWindowPos(g_hWndProgMgr, NULL,
|
||||
rcMainWindow.left, rcMainWindow.top,
|
||||
rcMainWindow.right - rcMainWindow.left,
|
||||
rcMainWindow.bottom - rcMainWindow.top, SWP_NOZORDER);
|
||||
|
||||
// Load the menus...
|
||||
hMenu = GetMenu(hWndProgMgr);
|
||||
hSystemMenu = GetSystemMenu(hWndProgMgr, FALSE);
|
||||
hMenu = GetMenu(g_hWndProgMgr);
|
||||
hSystemMenu = GetSystemMenu(g_hWndProgMgr, FALSE);
|
||||
|
||||
// Update relevant parts of the window
|
||||
UpdateChecks(bAutoArrange, IDM_OPTIONS, IDM_OPTIONS_AUTOARRANGE);
|
||||
@@ -142,31 +163,35 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||
|
||||
// Update settings based on their values
|
||||
if (bTopMost)
|
||||
SetWindowPos(hWndProgMgr, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
SetWindowPos(g_hWndProgMgr, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
if (bIsDefaultShell)
|
||||
if (g_bIsDefaultShell)
|
||||
{
|
||||
// Modify the context menus since we're the default shell
|
||||
DeleteMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND);
|
||||
|
||||
LoadString(hAppInstance, IDS_SHUTDOWN, szBuffer, ARRAYSIZE(szBuffer));
|
||||
LoadString(g_hAppInstance, IDS_SHUTDOWN, szBuffer, ARRAYSIZE(szBuffer));
|
||||
InsertMenu(hSystemMenu, 6, MF_BYPOSITION | MF_STRING, IDM_SHUTDOWN, szBuffer);
|
||||
ModifyMenu(hMenu, IDM_FILE_EXIT, MF_BYCOMMAND | MF_STRING, IDM_SHUTDOWN, szBuffer);
|
||||
|
||||
LoadString(hAppInstance, IDS_RUN, szBuffer, ARRAYSIZE(szBuffer));
|
||||
LoadString(g_hAppInstance, IDS_RUN, szBuffer, ARRAYSIZE(szBuffer));
|
||||
InsertMenu(hSystemMenu, 6, MF_BYPOSITION | MF_STRING, IDM_FILE_RUN, szBuffer);
|
||||
|
||||
LoadString(hAppInstance, IDS_TASKMGR, szBuffer, ARRAYSIZE(szBuffer));
|
||||
LoadString(g_hAppInstance, IDS_TASKMGR, szBuffer, ARRAYSIZE(szBuffer));
|
||||
InsertMenu(hSystemMenu, 6, MF_BYPOSITION | MF_STRING, IDM_TASKMGR, szBuffer);
|
||||
|
||||
// Create the desktop window...
|
||||
// CreateDesktopWindow();
|
||||
}
|
||||
|
||||
// Create the frame window
|
||||
if (!InitializeGroups())
|
||||
return FALSE;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0) > 0)
|
||||
{
|
||||
if (!TranslateMDISysAccel(hWndMDIClient, &msg) &&
|
||||
!TranslateAccelerator(hWndProgMgr, hAccel, &msg))
|
||||
!TranslateAccelerator(g_hWndProgMgr, hAccel, &msg))
|
||||
{
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
@@ -174,3 +199,34 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// NOTE(u130b8): We used to compile Release builds with /NODEFAULTLIB
|
||||
// but I've temporarily removed it so malloc and free works.
|
||||
|
||||
// NOTE(u130b8): We're compiling without the C runtime by default in Release builds.
|
||||
// But in Debug builds, we need the C runtime, otherwise the address sanitizer and
|
||||
// MSVC debug tools break because they use the wWinMainCRTStartup entrypoint to initialize.
|
||||
|
||||
#ifdef PROGMGR_RELEASE
|
||||
#pragma function(memset)
|
||||
void *memset(char* dst, int value, size_t count) {
|
||||
while (count--) { *dst++ = value; }
|
||||
return dst;
|
||||
}
|
||||
|
||||
#pragma function(memcpy)
|
||||
void *memcpy(char *dst, const char *src, size_t count) {
|
||||
while (count--) { *dst++ = *src++; }
|
||||
return dst;
|
||||
}
|
||||
|
||||
void __stdcall wWinMainCRTStartup() {
|
||||
int code = wWinMain(GetModuleHandle(0), 0, 0, 0);
|
||||
ExitProcess(code);
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
@@ -1,22 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Vortesys.ProgramManagerII.ProgMgr"
|
||||
version="2.0.0.0"
|
||||
processorArchitecture="*"
|
||||
/>
|
||||
<description>Program Manager II</description>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
@@ -33,20 +25,4 @@
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<!--
|
||||
UAC settings:
|
||||
- app should run at same integrity level as calling process
|
||||
- app does not need to manipulate windows belonging to
|
||||
higher-integrity-level processes
|
||||
-->
|
||||
<requestedExecutionLevel
|
||||
level="asInvoker"
|
||||
uiAccess="false"
|
||||
/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
PROGMGR.H -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's primary header file.
|
||||
LICENSE INFORMATION -
|
||||
@@ -9,11 +9,13 @@
|
||||
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
#pragma comment(lib, "ComCtl32.lib")
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
#pragma comment(lib, "Secur32.lib")
|
||||
|
||||
/* Includes */
|
||||
#include <wtypes.h>
|
||||
#pragma comment(lib, "UxTheme.lib")
|
||||
#pragma comment(lib, "Version.lib")
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
|
||||
/* Macros and Defines */
|
||||
#define GET_WM_COMMAND_ID(wParam, lParam) LOWORD(wParam)
|
||||
@@ -29,22 +31,25 @@
|
||||
#define RF_RETRY 0x0002 // Cancel the operation, but leave the dialog open
|
||||
|
||||
/* Global Variables */
|
||||
// PROGMGR.C
|
||||
extern BOOL bIsDefaultShell;
|
||||
extern HICON hProgMgrIcon;
|
||||
extern HICON hGroupIcon;
|
||||
extern HINSTANCE hAppInstance;
|
||||
extern HWND hWndProgMgr;
|
||||
extern HWND hWndMDIClient;
|
||||
extern WCHAR szAppTitle[32];
|
||||
extern WCHAR szProgMgr[];
|
||||
extern WCHAR szWebsite[64];
|
||||
extern WCHAR szClass[16];
|
||||
extern WCHAR szGrpClass[16];
|
||||
extern BOOL g_bIsDefaultShell;
|
||||
// Handles
|
||||
extern HINSTANCE g_hAppInstance;
|
||||
extern HWND g_hWndProgMgr;
|
||||
// Icons
|
||||
extern HICON g_hProgMgrIcon;
|
||||
extern HICON g_hGroupIcon;
|
||||
// Strings
|
||||
extern WCHAR g_szAppTitle[64];
|
||||
extern WCHAR g_szProgMgr[];
|
||||
extern WCHAR g_szWebsite[64];
|
||||
extern WCHAR g_szClass[16];
|
||||
// Permissions
|
||||
extern BOOL g_bPermAdmin; // Has Administrator permissions
|
||||
extern BOOL g_bPermGuest; // Has Guest permissions
|
||||
extern BOOL g_bPermPower; // Has power option permissions
|
||||
|
||||
/* Function Prototypes */
|
||||
// DESKTOP.C
|
||||
BOOL CreateDesktopWindow();// SYSINT.C
|
||||
BOOL UpdatePermissions(VOID);
|
||||
// SYSINT.C
|
||||
BOOL RunFileDlg(HWND hWndOwner, HICON hIcon, LPWSTR lpszDir, LPWSTR lpszTitle, LPWSTR lpszDesc, DWORD dwFlags);
|
||||
BOOL ExitWindowsDialog(HWND hWndOwner);
|
||||
@@ -53,4 +58,4 @@ BOOL SetShellWindow(HWND hWndShell);
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam);
|
||||
VOID UpdateChecks(BOOL bVarMenu, UINT uSubMenu, UINT uID);
|
||||
VOID UpdateWindowTitle();
|
||||
VOID UpdateWindowTitle(VOID);
|
||||
|
||||
@@ -29,26 +29,26 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -71,23 +71,23 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(OutDir)</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(OutDir)</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(OutDir)</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(OutDir)</IntDir>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
@@ -96,6 +96,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -104,6 +105,9 @@
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
@@ -113,6 +117,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -130,6 +135,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -138,6 +144,9 @@
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@@ -147,6 +156,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -159,13 +169,15 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="dialog.h" />
|
||||
<ClInclude Include="group.h" />
|
||||
<ClInclude Include="grpupdat.h" />
|
||||
<ClInclude Include="progmgr.h" />
|
||||
<ClInclude Include="registry.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="desktop.c" />
|
||||
<ClCompile Include="dialog.c" />
|
||||
<ClCompile Include="progmgr.c" />
|
||||
<ClCompile Include="registry.c" />
|
||||
<ClCompile Include="group.c" />
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
<Filter Include="Language Resources">
|
||||
<UniqueIdentifier>{71dbbd6d-c82a-4fac-a0ff-74be88190f82}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files\en-US">
|
||||
<UniqueIdentifier>{2a11d118-5a5c-4681-86dc-31de4f0251ff}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="progmgr.h">
|
||||
@@ -30,6 +33,12 @@
|
||||
<ClInclude Include="group.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="grpupdat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dialog.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="progmgr.c">
|
||||
@@ -38,9 +47,6 @@
|
||||
<ClCompile Include="registry.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="desktop.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sysint.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -50,16 +56,19 @@
|
||||
<ClCompile Include="group.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dialog.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resource.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="lang\dlg_en-US.rc">
|
||||
<Filter>Language Resources</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="lang\res_en-US.rc">
|
||||
<Filter>Language Resources</Filter>
|
||||
<Filter>Resource Files\en-US</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="lang\dlg_en-US.rc">
|
||||
<Filter>Resource Files\en-US</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
REGISTRY.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's registry and settings related functions.
|
||||
LICENSE INFORMATION -
|
||||
@@ -8,12 +8,13 @@
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#include "progmgr.h"
|
||||
#include "registry.h"
|
||||
// #define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "registry.h"
|
||||
|
||||
/* Variables */
|
||||
// Global HKEYs
|
||||
@@ -35,11 +36,12 @@ DWORD dwSettingsMask = {
|
||||
};
|
||||
RECT rcMainWindow;
|
||||
// Registry Subkeys
|
||||
PWSTR pszProgramGroups = L"Program Groups";
|
||||
PWSTR pszSettings = L"Settings";
|
||||
PWSTR pszProgramGroups = TEXT("Program Groups");
|
||||
PWSTR pszSettings = TEXT("Settings");
|
||||
// Settings Subkeys
|
||||
PWSTR pszSettingsWindow = L"Window";
|
||||
PWSTR pszSettingsMask = L"SettingsMask";
|
||||
PWSTR pszSettingsWindow = TEXT("Window");
|
||||
PWSTR pszSettingsMask = TEXT("SettingsMask");
|
||||
// Permissions (Global)
|
||||
|
||||
/* Functions */
|
||||
|
||||
@@ -50,15 +52,15 @@ PWSTR pszSettingsMask = L"SettingsMask";
|
||||
RETURNS -
|
||||
TRUE if successful, FALSE if unsuccessful.
|
||||
\* * * */
|
||||
BOOL InitializeRegistryKeys()
|
||||
BOOL InitializeRegistryKeys(VOID)
|
||||
{
|
||||
if (!RegCreateKeyEx(HKEY_CURRENT_USER, PROGMGR_KEY, 0, szProgMgr, 0,
|
||||
if (!RegCreateKeyEx(HKEY_CURRENT_USER, PROGMGR_KEY, 0, g_szProgMgr, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &hKeyProgramManager, NULL))
|
||||
{
|
||||
// Create Program Groups and Settings keys
|
||||
RegCreateKeyEx(hKeyProgramManager, pszProgramGroups, 0, szProgMgr, 0,
|
||||
RegCreateKeyEx(hKeyProgramManager, pszProgramGroups, 0, g_szProgMgr, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &hKeyProgramGroups, NULL);
|
||||
RegCreateKeyEx(hKeyProgramManager, pszSettings, 0, szProgMgr, 0,
|
||||
RegCreateKeyEx(hKeyProgramManager, pszSettings, 0, g_szProgMgr, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &hKeySettings, NULL);
|
||||
|
||||
return TRUE;
|
||||
@@ -73,20 +75,20 @@ BOOL InitializeRegistryKeys()
|
||||
TRUE if Program Manager is the default shell,
|
||||
FALSE if otherwise or an error occurs.
|
||||
\* * * */
|
||||
BOOL IsProgMgrDefaultShell()
|
||||
BOOL IsProgMgrDefaultShell(VOID)
|
||||
{
|
||||
HKEY hKeyWinlogon;
|
||||
WCHAR szShell[HKEYMAXLEN] = L"";
|
||||
WCHAR szShell[HKEYMAXLEN] = TEXT("");
|
||||
DWORD dwType;
|
||||
DWORD dwBufferSize = sizeof(szShell);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY,
|
||||
0, KEY_READ, &hKeyWinlogon) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(hKeyWinlogon, L"Shell", 0, &dwType,
|
||||
if (RegQueryValueEx(hKeyWinlogon, TEXT("Shell"), 0, &dwType,
|
||||
(LPBYTE)szShell, &dwBufferSize) == ERROR_SUCCESS)
|
||||
{
|
||||
if (StrStr(szShell, szProgMgr))
|
||||
if (StrStr(szShell, g_szProgMgr))
|
||||
{
|
||||
// ProgMgr detected >:)
|
||||
RegCloseKey(hKeyWinlogon);
|
||||
@@ -110,24 +112,63 @@ BOOL IsProgMgrDefaultShell()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RegistrySaveGroup -
|
||||
Saves a group structure to the registry.
|
||||
RETURNS -
|
||||
RCE_* configuration error value
|
||||
\* * * */
|
||||
DWORD RegistrySaveGroup(_In_ PGROUP pg)
|
||||
{
|
||||
// If the pointer or HKEY is invalid then fail out
|
||||
if ((pg == NULL) || (hKeyProgramGroups == NULL))
|
||||
return RCE_FAILURE;
|
||||
|
||||
// Save group
|
||||
UpdateGroup(pg);
|
||||
if (!RegSetValueEx(hKeyProgramGroups, pg->szName, 0, REG_BINARY,
|
||||
(const BYTE*)pg, sizeof(*pg)) == ERROR_SUCCESS)
|
||||
return RCE_GROUPS;
|
||||
|
||||
return RCE_SUCCESS;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
RegistryRemoveGroup -
|
||||
Removes a group structure from the registry.
|
||||
RETURNS -
|
||||
RCE_* configuration error value
|
||||
\* * * */
|
||||
DWORD RegistryRemoveGroup(_In_ PGROUP pg)
|
||||
{
|
||||
// If the pointer or HKEY is invalid then fail out
|
||||
if ((pg == NULL) || (hKeyProgramGroups == NULL))
|
||||
return RCE_FAILURE;
|
||||
|
||||
// Try to remove the group matching the name
|
||||
// If we fail, group does not exist in the registry
|
||||
if (RegDeleteValue(hKeyProgramGroups, pg->szName) != ERROR_SUCCESS)
|
||||
return RCE_FAILURE;
|
||||
|
||||
return RCE_SUCCESS;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
SaveConfig -
|
||||
Finds and collapses all settings
|
||||
and saves them to the registry.
|
||||
RETURNS -
|
||||
TRUE if successful, FALSE if unsuccessful.
|
||||
RCE_* configuration error value
|
||||
\* * * */
|
||||
BOOL SaveConfig(BOOL bPos, BOOL bSettings, BOOL bGroups)
|
||||
DWORD SaveConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups, _In_ BOOL bExit)
|
||||
{
|
||||
BOOL bConfigStatus = TRUE;
|
||||
WINDOWPLACEMENT wpProgMgr;
|
||||
RECT rcWindow;
|
||||
DWORD dwConfigStatus = RCE_SUCCESS;
|
||||
|
||||
if (bSettings)
|
||||
{
|
||||
// Shrink the settings into the bitmask and save it
|
||||
// There's definitely a better way to do this but...
|
||||
// I'll get to it later :)
|
||||
// TODO: do this more efficiently
|
||||
dwSettingsMask =
|
||||
(bAutoArrange && PMS_AUTOARRANGE) * PMS_AUTOARRANGE |
|
||||
(bMinOnRun && PMS_MINONRUN) * PMS_MINONRUN |
|
||||
@@ -137,54 +178,229 @@ BOOL SaveConfig(BOOL bPos, BOOL bSettings, BOOL bGroups)
|
||||
|
||||
if (!RegSetValueEx(hKeySettings, pszSettingsMask, 0, REG_DWORD,
|
||||
(const BYTE*)&dwSettingsMask, sizeof(dwSettingsMask)) == ERROR_SUCCESS)
|
||||
bConfigStatus = FALSE;
|
||||
dwConfigStatus = dwConfigStatus && RCE_SETTINGS;
|
||||
}
|
||||
|
||||
if (bPos)
|
||||
{
|
||||
WINDOWPLACEMENT wpProgMgr = { 0 };
|
||||
RECT rcWindow;
|
||||
|
||||
// Get and save window position
|
||||
wpProgMgr.length = sizeof(WINDOWPLACEMENT);
|
||||
GetWindowPlacement(hWndProgMgr, &wpProgMgr);
|
||||
GetWindowPlacement(g_hWndProgMgr, &wpProgMgr);
|
||||
CopyRect(&rcWindow, &wpProgMgr.rcNormalPosition);
|
||||
|
||||
if (!RegSetValueEx(hKeySettings, pszSettingsWindow, 0, REG_BINARY,
|
||||
(const BYTE*)&rcWindow, sizeof(rcWindow)) == ERROR_SUCCESS)
|
||||
bConfigStatus = FALSE;
|
||||
dwConfigStatus = dwConfigStatus && RCE_POSITION;
|
||||
}
|
||||
|
||||
return bConfigStatus;
|
||||
if (bGroups)
|
||||
{
|
||||
HWND hWndGroup = NULL;
|
||||
|
||||
EnumChildWindows(hWndMDIClient, &SaveWindowEnumProc, (LPARAM)bExit);
|
||||
}
|
||||
|
||||
return dwConfigStatus;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
BOOL LoadConfig() -
|
||||
SaveWindowEnumProc() -
|
||||
Procedure for enumeration
|
||||
of group windows to save
|
||||
or close them
|
||||
NOTES -
|
||||
lParam is a BOOL that determines
|
||||
whether to close the group or not
|
||||
RETURNS -
|
||||
TRUE to continue
|
||||
FALSE to stop
|
||||
\* * * */
|
||||
BOOL CALLBACK SaveWindowEnumProc(HWND hWndGroup, LPARAM lParam)
|
||||
{
|
||||
PGROUP pNewGroup = NULL;
|
||||
PGROUP pGroup = NULL;
|
||||
|
||||
if (hWndGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA);
|
||||
|
||||
if (pGroup == NULL)
|
||||
return FALSE;
|
||||
|
||||
// lean it...
|
||||
/*pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 1, 1));
|
||||
if (pNewGroup != NULL)
|
||||
{
|
||||
pGroup = pNewGroup;
|
||||
SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup);
|
||||
}*/
|
||||
|
||||
// save it...
|
||||
if (RegistrySaveGroup(pGroup) != RCE_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
// close it...
|
||||
if ((BOOL)lParam == TRUE)
|
||||
{
|
||||
RemoveGroup(hWndGroup, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
LoadConfig() -
|
||||
Finds all settings and retrieves them
|
||||
from the registry.
|
||||
RETURNS -
|
||||
TRUE if successful, FALSE if unsuccessful.
|
||||
RCE_* configuration error value
|
||||
\* * * */
|
||||
BOOL LoadConfig()
|
||||
DWORD LoadConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups)
|
||||
{
|
||||
BOOL bConfigStatus = TRUE;
|
||||
DWORD dwType;
|
||||
DWORD dwBufferSize = sizeof(dwSettingsMask);
|
||||
DWORD dwRectBufferSize = sizeof(rcMainWindow);
|
||||
DWORD dwConfigStatus = RCE_SUCCESS;
|
||||
|
||||
// Load settings bitmask
|
||||
if (!RegQueryValueEx(hKeySettings, pszSettingsMask, 0, &dwType,
|
||||
(LPBYTE)&dwSettingsMask, &dwBufferSize) == ERROR_SUCCESS)
|
||||
bConfigStatus = FALSE;
|
||||
|
||||
// Apply bitmask to booleans
|
||||
bAutoArrange = (dwSettingsMask & PMS_AUTOARRANGE);
|
||||
bMinOnRun = (dwSettingsMask & PMS_MINONRUN);
|
||||
bTopMost = (dwSettingsMask & PMS_TOPMOST);
|
||||
bSaveSettings = (dwSettingsMask & PMS_SAVESETTINGS);
|
||||
bShowUsername = (dwSettingsMask & PMS_SHOWUSERNAME);
|
||||
if (bSettings)
|
||||
{
|
||||
DWORD dwBufferSize = sizeof(dwSettingsMask);
|
||||
DWORD dwType = REG_DWORD;
|
||||
|
||||
// Load window position... and apply it!
|
||||
if (!RegQueryValueEx(hKeySettings, pszSettingsWindow, 0, &dwType,
|
||||
(LPBYTE)&rcMainWindow, &dwRectBufferSize) == ERROR_SUCCESS)
|
||||
bConfigStatus = FALSE;
|
||||
// Load settings bitmask
|
||||
if (!RegQueryValueEx(hKeySettings, pszSettingsMask, 0, &dwType,
|
||||
(LPBYTE)&dwSettingsMask, &dwBufferSize) == ERROR_SUCCESS)
|
||||
dwConfigStatus = dwConfigStatus && RCE_SETTINGS;
|
||||
|
||||
return bConfigStatus;
|
||||
// Apply bitmask to booleans
|
||||
bAutoArrange = (dwSettingsMask & PMS_AUTOARRANGE);
|
||||
bMinOnRun = (dwSettingsMask & PMS_MINONRUN);
|
||||
bTopMost = (dwSettingsMask & PMS_TOPMOST);
|
||||
bSaveSettings = (dwSettingsMask & PMS_SAVESETTINGS);
|
||||
bShowUsername = (dwSettingsMask & PMS_SHOWUSERNAME);
|
||||
}
|
||||
|
||||
if (bPos)
|
||||
{
|
||||
DWORD dwRectBufferSize = sizeof(rcMainWindow);
|
||||
DWORD dwType = REG_BINARY;
|
||||
|
||||
// Load window position
|
||||
if (!RegQueryValueEx(hKeySettings, pszSettingsWindow, 0, &dwType,
|
||||
(LPBYTE)&rcMainWindow, &dwRectBufferSize) == ERROR_SUCCESS)
|
||||
dwConfigStatus = dwConfigStatus && RCE_POSITION;
|
||||
}
|
||||
|
||||
if (bGroups)
|
||||
{
|
||||
DWORD dwBufferSize = sizeof(dwSettingsMask);
|
||||
DWORD dwType = REG_BINARY;
|
||||
UINT cGroupVals = 0;
|
||||
|
||||
OutputDebugString(TEXT("REGISTRY.C: Loading groups...\n"));
|
||||
|
||||
// Get the num of group values, if we fail then ABORT!
|
||||
if (!(RegQueryInfoKey(hKeyProgramGroups, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, &cGroupVals,
|
||||
NULL, NULL, NULL, NULL) == ERROR_SUCCESS))
|
||||
{
|
||||
dwConfigStatus = dwConfigStatus && RCE_SETTINGS;
|
||||
|
||||
// I can get away with returning here upon
|
||||
// failure since this is the last one
|
||||
OutputDebugString(TEXT("REGISTRY.C: Failed to get # of values!\n"));
|
||||
return dwConfigStatus;
|
||||
}
|
||||
|
||||
// Enumerate through the registry values
|
||||
if (cGroupVals)
|
||||
{
|
||||
DWORD i = 0;
|
||||
|
||||
for (i = 0; i < cGroupVals; i++)
|
||||
{
|
||||
WCHAR szGroupValName[MAX_TITLE_LENGTH] = TEXT("");
|
||||
UINT cbGroupValName = ARRAYSIZE(szGroupValName);
|
||||
UINT cbGroup = 0;
|
||||
PGROUP pGroup = NULL;
|
||||
LSTATUS error = ERROR_SUCCESS;
|
||||
|
||||
// TODO: figure out where i'm really going to store the
|
||||
// group name, if not in the group structure then in
|
||||
// the name of the registry key (val 3 here)
|
||||
|
||||
// get the size of the group
|
||||
error = RegEnumValue(hKeyProgramGroups, i, (LPWSTR)&szGroupValName,
|
||||
&cbGroupValName, NULL, NULL, NULL, &cbGroup);
|
||||
|
||||
if (error == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
else if (error != ERROR_SUCCESS)
|
||||
{
|
||||
OutputDebugString(TEXT("REGISTRY.C: RegEnumValue failure.\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// allocate memory for the group
|
||||
pGroup = malloc(cbGroup);
|
||||
|
||||
if (pGroup == NULL)
|
||||
{
|
||||
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
|
||||
return dwConfigStatus;
|
||||
}
|
||||
|
||||
// retrieve the group
|
||||
error = RegGetValue(hKeyProgramGroups, NULL, szGroupValName, RRF_RT_REG_BINARY, NULL, pGroup, &cbGroup);
|
||||
|
||||
if (error == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
OutputDebugString(TEXT("REGISTRY.C: Group not found!\n"));
|
||||
|
||||
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
|
||||
}
|
||||
if (error == ERROR_MORE_DATA)
|
||||
{
|
||||
OutputDebugString(TEXT("REGISTRY.C: Buffer too small!\n"));
|
||||
|
||||
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
|
||||
}
|
||||
else if (error != ERROR_SUCCESS)
|
||||
{
|
||||
OutputDebugString(TEXT("REGISTRY.C: Group retrieval failed!\n"));
|
||||
|
||||
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
|
||||
}
|
||||
else
|
||||
OutputDebugString(TEXT("REGISTRY.C: Group retrieved.\n"));
|
||||
|
||||
// create the group
|
||||
if (pGroup)
|
||||
{
|
||||
if (pGroup->dwSignature == GRP_SIGNATURE)
|
||||
{
|
||||
CreateGroup(pGroup);
|
||||
OutputDebugString(TEXT("REGISTRY.C: Group created.\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugString(TEXT("REGISTRY.C: Group creation aborted.\n"));
|
||||
}
|
||||
|
||||
// free memory
|
||||
free(pGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
|
||||
OutputDebugString(TEXT("REGISTRY.C: Failed to create group!\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dwConfigStatus;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
REGISTRY.H -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's header file for registry related functions.
|
||||
LICENSE INFORMATION -
|
||||
@@ -10,17 +10,20 @@
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Includes */
|
||||
#include <wtypes.h>
|
||||
|
||||
/* Defines */
|
||||
#define HKEYMAXLEN 261
|
||||
// Key Paths
|
||||
#define WINLOGON_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"
|
||||
// #define PROGMAN_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager"
|
||||
// #define WINDOWS_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
|
||||
#define PROGMGR_KEY L"Software\\Vortesys\\Program Manager II"
|
||||
// Settings Bitmask Values (DWORD)
|
||||
#define WINLOGON_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
|
||||
// #define PROGMAN_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager")
|
||||
// #define WINDOWS_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows")
|
||||
#define PROGMGR_KEY TEXT("Software\\Vortesys\\Program Manager II")
|
||||
// Registry configuration error values (DWORD)
|
||||
#define RCE_SUCCESS 0x0000000
|
||||
#define RCE_FAILURE 0x0000001
|
||||
#define RCE_SETTINGS 0x0000002
|
||||
#define RCE_POSITION 0x0000004
|
||||
#define RCE_GROUPS 0x0000008
|
||||
// Settings values (DWORD)
|
||||
#define PMS_AUTOARRANGE 0x00000001
|
||||
#define PMS_MINONRUN 0x00000002
|
||||
#define PMS_TOPMOST 0x00000004
|
||||
@@ -43,5 +46,11 @@ extern RECT rcMainWindow;
|
||||
/* Function Prototypes */
|
||||
BOOL InitializeRegistryKeys(VOID);
|
||||
BOOL IsProgMgrDefaultShell(VOID);
|
||||
BOOL LoadConfig(VOID);
|
||||
BOOL SaveConfig(BOOL bPos, BOOL bSettings, BOOL bGroups);
|
||||
// Groups
|
||||
DWORD RegistrySaveGroup(_In_ PGROUP pg);
|
||||
DWORD RegistryRemoveGroup(_In_ PGROUP pg);
|
||||
// Settings
|
||||
DWORD SaveConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups, _In_ BOOL bExit);
|
||||
DWORD LoadConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups);
|
||||
// Miscellaneous
|
||||
BOOL CALLBACK SaveWindowEnumProc(HWND hWndGroup, LPARAM lParam);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
/* * * * * * * *\
|
||||
RESOURCE.RC -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
This file contains Program Manager's resources.
|
||||
LICENSE INFORMATION -
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/* Necessary Evil */
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include <afxres.h>
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
@@ -17,19 +17,26 @@
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(65001) // UTF-8
|
||||
#include "lang\res_en-US.rc" // English (US)
|
||||
#include "lang\dlg_en-US.rc" // English (US)
|
||||
|
||||
/* Icon Library */
|
||||
// Primary
|
||||
#ifndef _DEBUG
|
||||
IDI_PROGMGR ICON icons\progmgr.ico
|
||||
#else
|
||||
IDI_PROGMGR ICON icons\progmgrd.ico
|
||||
#endif
|
||||
IDI_PROGGRP ICON icons\pmgroup.ico
|
||||
IDI_PROGITM ICON icons\pmitem.ico
|
||||
IDI_COMMON ICON icons\common.ico
|
||||
IDI_PERSONAL ICON icons\personal.ico
|
||||
// Secondary
|
||||
IDI_COMMS ICON icons\comms.ico
|
||||
IDI_CONSOLE ICON icons\console.ico
|
||||
IDI_DOCUMENT ICON icons\document.ico
|
||||
IDI_SPREADSHEET ICON icons\spsheet.ico
|
||||
// IDI_COMMS ICON icons\comms.ico
|
||||
// IDI_CONSOLE ICON icons\console.ico
|
||||
// IDI_DOCUMENT ICON icons\document.ico
|
||||
// IDI_SPREADSHEET ICON icons\spsheet.ico
|
||||
// Tertiary
|
||||
IDI_SUPERMAN ICON icons\misc\superman.ico
|
||||
// IDI_SUPERMAN ICON icons\misc\superman.ico
|
||||
|
||||
/* Manifest */
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "progmgr.exe.manifest"
|
||||
@@ -38,6 +45,13 @@ CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "progmgr.exe.manifest"
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "version.inc"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
|
||||
// NOTE(u130b8): Example of using PROGMGR_GIT_HASH in the resource file
|
||||
#ifdef PROGMGR_GIT_HASH
|
||||
#undef VER_PRODUCTVERSION_STR
|
||||
#define VER_PRODUCTVERSION_STR "git-" PROGMGR_GIT_HASH
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/* * * * * * * *\
|
||||
SYSINT.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's system interface functions.
|
||||
Program Manager's system export functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#include "progmgr.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include "progmgr.h"
|
||||
|
||||
/* Functions */
|
||||
|
||||
@@ -27,7 +27,7 @@ BOOL RunFileDlg(HWND hWndOwner,
|
||||
LPWSTR lpszDesc,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
HMODULE hLib = LoadLibrary(L"shell32.dll");
|
||||
HMODULE hLib = LoadLibrary(TEXT("shell32.dll"));
|
||||
|
||||
if (hLib)
|
||||
{
|
||||
@@ -50,7 +50,7 @@ BOOL RunFileDlg(HWND hWndOwner,
|
||||
\* * * */
|
||||
BOOL ExitWindowsDialog(HWND hWndOwner)
|
||||
{
|
||||
HMODULE hLib = LoadLibrary(L"shell32.dll");
|
||||
HMODULE hLib = LoadLibrary(TEXT("shell32.dll"));
|
||||
|
||||
if (hLib)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ BOOL ExitWindowsDialog(HWND hWndOwner)
|
||||
\* * * */
|
||||
BOOL SetShellWindow(HWND hWndShell)
|
||||
{
|
||||
HMODULE hLib = GetModuleHandle(L"user32.dll");
|
||||
HMODULE hLib = GetModuleHandle(TEXT("user32.dll"));
|
||||
|
||||
if (hLib)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* * * * * * * *\
|
||||
WNDPROC.C -
|
||||
Copyright (c) 2023 freedom7341, Vortesys
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's window procedure.
|
||||
LICENSE INFORMATION -
|
||||
@@ -8,16 +8,19 @@
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
// #define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define SECURITY_WIN32
|
||||
#include <Windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <shellapi.h>
|
||||
#include <Lmcons.h>
|
||||
#include <security.h>
|
||||
#include <Mmsystem.h>
|
||||
#include "progmgr.h"
|
||||
#include "dialog.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
|
||||
/* Functions */
|
||||
|
||||
@@ -31,74 +34,53 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
|
||||
case WM_CREATE:
|
||||
{
|
||||
// Play the logon sound. (But only if we're the default shell)
|
||||
if (g_bIsDefaultShell)
|
||||
PlaySound(TEXT("WindowsLogon"), NULL, SND_ALIAS | SND_ASYNC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
if ((wParam >= IDM_MAIN) && (wParam <= IDM_TASKMGR))
|
||||
{
|
||||
CLIENTCREATESTRUCT ccs;
|
||||
RECT rc;
|
||||
|
||||
// Frame Window
|
||||
hWndProgMgr = hWnd;
|
||||
|
||||
// Create the MDI Client Window
|
||||
ccs.hWindowMenu = GetSubMenu(GetMenu(hWnd), IDM_WINDOW);
|
||||
ccs.idFirstChild = IDM_WINDOW_CHILDSTART;
|
||||
|
||||
GetClientRect(hWndProgMgr, &rc);
|
||||
|
||||
if (!(hWndMDIClient = CreateWindowEx(WS_EX_COMPOSITED, L"MDIClient",
|
||||
NULL, WS_CLIPCHILDREN | WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
hWnd, (HMENU)1, hAppInstance, (LPWSTR)&ccs)))
|
||||
if (wParam == IDM_TASKMGR)
|
||||
{
|
||||
return FALSE;
|
||||
ShellExecute(g_hWndProgMgr, TEXT("open"), TEXT("TASKMGR.EXE"), NULL, NULL, SW_NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TempCreateGroup(hWndMDIClient);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
if ((wParam >= IDM_MAIN) || (wParam <= IDM_TASKMGR))
|
||||
{
|
||||
if (wParam == IDM_TASKMGR)
|
||||
{
|
||||
ShellExecute(hWndProgMgr, L"open", L"TASKMGR.EXE", NULL, NULL, SW_NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CmdProc(hWnd, wParam, lParam))
|
||||
return 0;
|
||||
}
|
||||
|
||||
goto WndProcDefault;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
if (CmdProc(hWnd, wParam, lParam))
|
||||
return 0;
|
||||
|
||||
goto WndProcDefault;
|
||||
|
||||
case WM_CLOSE:
|
||||
if (bSaveSettings)
|
||||
SaveConfig(TRUE, TRUE, TRUE);
|
||||
|
||||
if (bIsDefaultShell && (GetShellWindow() != NULL))
|
||||
SetShellWindow(0);
|
||||
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
WndProcDefault:
|
||||
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
if (CmdProc(hWnd, wParam, lParam))
|
||||
return 0;
|
||||
|
||||
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
|
||||
|
||||
case WM_CLOSE:
|
||||
case WM_ENDSESSION:
|
||||
if (bSaveSettings)
|
||||
SaveConfig(TRUE, TRUE, TRUE, TRUE);
|
||||
|
||||
if (g_bIsDefaultShell && (GetShellWindow() != NULL))
|
||||
SetShellWindow(0);
|
||||
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -115,9 +97,25 @@ LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
case IDM_SHUTDOWN:
|
||||
ExitWindowsDialog(hWnd);
|
||||
DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_POWER), hWnd, (DLGPROC)ShutdownDlgProc);
|
||||
break;
|
||||
|
||||
|
||||
case IDM_FILE_NEW_GROUP:
|
||||
DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_GROUP), hWnd, (DLGPROC)NewGroupDlgProc);
|
||||
break;
|
||||
|
||||
case IDM_FILE_NEW_ITEM:
|
||||
DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_ITEM), hWnd, (DLGPROC)NewItemDlgProc);
|
||||
break;
|
||||
|
||||
case IDM_FILE_OPEN:
|
||||
case IDM_FILE_MOVE:
|
||||
case IDM_FILE_COPY:
|
||||
case IDM_FILE_DELETE:
|
||||
case IDM_FILE_PROPS:
|
||||
SendMessage((HWND)SendMessage(hWnd, WM_MDIGETACTIVE, (WPARAM)NULL, (LPARAM)NULL), WM_COMMAND, wParam, lParam);
|
||||
break;
|
||||
|
||||
case IDM_FILE_RUN:
|
||||
RunFileDlg(hWnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
|
||||
break;
|
||||
@@ -138,7 +136,7 @@ LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
case IDM_OPTIONS_TOPMOST:
|
||||
bTopMost = !bTopMost;
|
||||
SetWindowPos(hWndProgMgr, bTopMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
SetWindowPos(g_hWndProgMgr, bTopMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
UpdateChecks(bTopMost, IDM_OPTIONS, IDM_OPTIONS_TOPMOST);
|
||||
goto SaveConfig;
|
||||
|
||||
@@ -154,24 +152,52 @@ LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
goto SaveConfig;
|
||||
|
||||
case IDM_OPTIONS_SAVENOW:
|
||||
SaveConfig:
|
||||
SaveConfig(TRUE, TRUE, TRUE);
|
||||
SaveConfig:
|
||||
SaveConfig(TRUE, TRUE, TRUE, FALSE);
|
||||
break;
|
||||
|
||||
case IDM_WINDOW_CASCADE:
|
||||
SendMessage(hWndMDIClient, WM_MDICASCADE, 0, 0);
|
||||
break;
|
||||
|
||||
case IDM_WINDOW_TILE:
|
||||
SendMessage(hWndMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0);
|
||||
break;
|
||||
|
||||
case IDM_WINDOW_TILEHORIZONTALLY:
|
||||
SendMessage(hWndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
|
||||
break;
|
||||
|
||||
case IDM_WINDOW_ARRANGEICONS:
|
||||
SendMessage(hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
|
||||
break;
|
||||
|
||||
case IDM_HELP_INDEX:
|
||||
ShellExecute(NULL, L"open", szWebsite, NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecute(NULL, TEXT("open"), g_szWebsite, NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
|
||||
case IDM_HELP_ABOUT:
|
||||
{
|
||||
WCHAR szTitle[40];
|
||||
|
||||
LoadString(hAppInstance, IDS_APPTITLE, szTitle, ARRAYSIZE(szTitle));
|
||||
ShellAbout(hWndProgMgr, szTitle, NULL, hProgMgrIcon);
|
||||
LoadString(g_hAppInstance, IDS_APPTITLE, szTitle, ARRAYSIZE(szTitle));
|
||||
ShellAbout(g_hWndProgMgr, szTitle, NULL, g_hProgMgrIcon);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (GET_WM_COMMAND_ID(wParam, lParam) >= IDM_WINDOW_CHILDSTART)
|
||||
{
|
||||
DefFrameProc(hWnd, hWndMDIClient, 0, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
HWND hChild = (HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, 0);
|
||||
if (hChild)
|
||||
{
|
||||
SendMessage(hChild, WM_COMMAND, wParam, lParam);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -188,7 +214,7 @@ VOID UpdateChecks(BOOL bVarMenu, UINT uSubMenu, UINT uID)
|
||||
{
|
||||
HMENU hMenu;
|
||||
|
||||
hMenu = GetMenu(hWndProgMgr);
|
||||
hMenu = GetMenu(g_hWndProgMgr);
|
||||
CheckMenuItem(hMenu, uID, (WORD)(bVarMenu ? MF_CHECKED : MF_UNCHECKED));
|
||||
|
||||
return;
|
||||
@@ -201,36 +227,25 @@ VOID UpdateChecks(BOOL bVarMenu, UINT uSubMenu, UINT uID)
|
||||
RETURNS -
|
||||
Nothing!
|
||||
\* * * */
|
||||
VOID UpdateWindowTitle()
|
||||
VOID UpdateWindowTitle(VOID)
|
||||
{
|
||||
WCHAR szUsername[UNLEN + 1] = L"";
|
||||
WCHAR szUsername[UNLEN] = TEXT("");
|
||||
DWORD dwUsernameLen = UNLEN;
|
||||
WCHAR szWindowTitle[UNLEN + ARRAYSIZE(szAppTitle) + 4] = L"";
|
||||
WCHAR szWindowTitle[UNLEN + ARRAYSIZE(g_szAppTitle) + 4] = TEXT("");
|
||||
|
||||
// Get user and domain name
|
||||
GetUserNameEx(NameSamCompatible, szUsername, &dwUsernameLen);
|
||||
|
||||
// Add username to window title if settings permit
|
||||
StringCchCopy(szWindowTitle, ARRAYSIZE(szAppTitle), szAppTitle);
|
||||
StringCchCopy(szWindowTitle, ARRAYSIZE(g_szAppTitle), g_szAppTitle);
|
||||
|
||||
if (bShowUsername)
|
||||
{
|
||||
StringCchCat(szWindowTitle, ARRAYSIZE(szWindowTitle), L" - ");
|
||||
StringCchCat(szWindowTitle, ARRAYSIZE(szWindowTitle), TEXT(" - "));
|
||||
StringCchCat(szWindowTitle, ARRAYSIZE(szWindowTitle), szUsername);
|
||||
}
|
||||
|
||||
SetWindowText(hWndProgMgr, (LPCWSTR)&szWindowTitle);
|
||||
SetWindowText(g_hWndProgMgr, (LPCWSTR)&szWindowTitle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
ChildWndProc -
|
||||
Program Manager's window procedure.
|
||||
RETURNS -
|
||||
Zero if nothing, otherwise returns the good stuff.
|
||||
\* * * */
|
||||
LRESULT CALLBACK ChildWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||