192 Commits

Author SHA1 Message Date
5998c235f1 Upload files to "/"
Some checks failed
MSBuild / build (Debug, x64) (push) Has been cancelled
MSBuild / build (Debug, x86) (push) Has been cancelled
MSBuild / build (Release, x64) (push) Has been cancelled
MSBuild / build (Release, x86) (push) Has been cancelled
2026-02-27 13:41:14 +00:00
Brady McDermott
caa84730cc I dont know no more 2024-10-22 11:54:40 -06:00
Brady McDermott
7410e6ddb1 pretty code 2024-10-22 03:35:39 -06:00
Brady McDermott
04d5187a36 fix warning 2024-10-22 03:32:21 -06:00
Brady McDermott
56084fefb7 remove probably useless +1 2024-10-22 03:28:30 -06:00
Brady McDermott
51561cd0ac increment version cause we made loads of progress!!! 2024-10-22 03:26:29 -06:00
Brady McDermott
c58b785b7b update readme and banner 2024-10-22 03:22:27 -06:00
Brady McDermott
841128b2f3 get rid of unused assets 2024-10-22 03:10:58 -06:00
Brady McDermott
13b4657c5b changes 2024-10-22 03:09:21 -06:00
Brady McDermott
8f6af5bba9 so real 2024-10-22 00:20:57 -06:00
Brady McDermott
b679f71607 let's go gambling 2024-10-21 18:34:06 -06:00
Brady McDermott
154bed9106 remove all the +1 ill probably be okay without them 2024-10-21 18:27:21 -06:00
Brady McDermott
b13ce0578b less maintenance if i do it thi way 2024-10-21 17:31:52 -06:00
Brady McDermott
9c6fe40c1c Solve issue #11 2024-10-21 16:06:39 -06:00
Brady McDermott
ca4b30e1d7 fix release icon 2024-10-21 00:25:27 -06:00
Brady McDermott
793c6a626f move other stuff to misc directory 2024-10-20 21:43:47 -06:00
Brady McDermott
892db32a81 Now put them back in the "progmgr" folder 2024-10-20 21:20:53 -06:00
Brady McDermott
69a624e0f9 GET RID OF the ProgMgr directory on GITHUB!!! 2024-10-20 21:20:00 -06:00
Brady McDermott
4a8ef09334 rename directory 2024-10-20 21:18:56 -06:00
Brady McDermott
cc62e8dc38 rename dir 1 2024-10-20 21:18:14 -06:00
Brady McDermott
b335db994a registry.... wndproc 2024-10-20 21:15:17 -06:00
Brady McDermott
21271a7c4b Delete progmgr/progmgr.vcxproj 2024-10-20 21:14:25 -06:00
Brady McDermott
0fa28c9e3e Delete progmgr/progmgr.vcxproj.filters 2024-10-20 21:14:18 -06:00
Brady McDermott
2c1fa58da6 cheaper listview resize 2024-10-20 17:05:27 -06:00
Brady McDermott
f6b7c29d2c Update group.c
lol if itbwoeks... programming from my phone..
2024-10-20 02:03:29 -06:00
Brady McDermott
d2342e80f5 save window pos/placement for program groups 2024-10-20 01:40:07 -06:00
Brady McDermott
306621f084 fix registry loading once and for all or something 2024-10-20 00:54:56 -06:00
Brady McDermott
f0ae48cd10 it no longer freezes on startup and falls into an infinite loop of loading program groups (that may or may not exist!) 2024-10-20 00:23:32 -06:00
Brady McDermott
aef812ae92 we don't use and don't need the app heap 2024-10-19 23:25:49 -06:00
Brady McDermott
50a290d57e lang res 2024-10-19 23:25:02 -06:00
Brady McDermott
93ca902e1f add:
startup sound when set as default shell
rename global variables for easier identification
2024-10-19 23:24:53 -06:00
Brady McDermott
7234547e3d remove unused filter 2024-07-30 22:58:40 -06:00
Brady McDermott
8f5bdce45b yeah 2024-07-30 22:20:56 -06:00
Brady McDermott
fdc0d28ab7 fix output dir 2024-07-30 22:19:58 -06:00
Brady McDermott
e0670bea6d caps 2024-07-30 22:18:38 -06:00
Brady McDermott
bcd6716fcb license year 2024-07-30 22:18:31 -06:00
Brady McDermott
e3187f62c3 reorganize and move things out of headers 2024-07-30 22:08:30 -06:00
Brady McDermott
174edb0aaa use v142 tools again 2024-07-30 22:02:05 -06:00
Brady McDermott
654dbf6be0 happy new years 2024-07-30 22:01:18 -06:00
Brady McDermott
7ea2d75f37 TODO: get rid of all the TODO comments 2024-04-02 14:40:33 -06:00
Brady McDermott
7602f6df4d readme 2024-04-01 17:53:20 -06:00
Brady McDermott
e8e91d87cd yeah that'll do'er 2024-03-30 18:23:10 -06:00
Brady McDermott
91216a8778 upload artifacts 2024-03-30 18:19:42 -06:00
Brady McDermott
f94859613c update msbuild and action checkout 2024-03-30 18:10:56 -06:00
Brady McDermott
1beddc7695 try it again... 2024-03-30 18:03:05 -06:00
Brady McDermott
69baa0e28c Update msbuild.yml 2024-03-30 17:56:42 -06:00
Brady McDermott
34026dbc8d lord please 2024-03-30 17:48:46 -06:00
Brady McDermott
fef15a326d hohoho 2024-03-30 17:30:55 -06:00
Brady McDermott
a07aace682 please build 2024-03-30 17:06:09 -06:00
Brady McDermott
39d2983852 Revert "Update msbuild.yml???"
This reverts commit 972c56a15b.
2024-03-30 16:44:36 -06:00
Brady McDermott
e7ad120d92 nuke vs2010 support 2024-03-30 13:03:09 -06:00
Brady McDermott
8939e71a99 i don't know what i was doing here
this is all getting rewritten
2024-03-30 13:01:12 -06:00
freedom
7a3c1ae092 Update msbuild.yml 2023-12-04 13:50:54 -07:00
freedom
67513d7c23 Update msbuild.yml 2023-12-04 13:50:19 -07:00
freedom
360aa81df6 Update msbuild.yml 2023-12-04 13:45:34 -07:00
freedom
c6cfed377a Update msbuild.yml 2023-12-04 13:44:52 -07:00
freedom
f18779ef28 moar yml 2023-12-04 13:41:24 -07:00
freedom
a570e61c8b Merge branch 'master' of https://github.com/Vortesys/Program-Manager-II 2023-12-04 13:30:37 -07:00
freedom
28e7fa0ad7 registry file update 2023-12-04 13:29:59 -07:00
Brady McDermott
972c56a15b Update msbuild.yml??? 2023-12-04 13:25:26 -07:00
Brady McDermott
7dd1875e1d i hate this 2023-10-28 22:15:24 -06:00
Brady McDermott
f1e0a17b3d sorta load items 2023-10-25 13:51:57 -06:00
Brady McDermott
c1dd3ae999 GROUPS LOAD 2023-10-25 11:49:37 -06:00
Brady McDermott
309ce4702b pain; suffering 2023-10-24 19:38:51 -06:00
Brady McDermott
5e878f98cf load gorup? 2023-10-24 15:43:10 -06:00
Brady McDermott
2c86c796f5 de bug 2023-10-24 08:24:34 -06:00
Brady McDermott
2e7dafbbac i lied 2023-10-23 16:39:44 -06:00
Brady McDermott
961cedb975 vista compatibility and vs2010 compile
final commit solely focused on this
2023-10-23 16:26:17 -06:00
Brady McDermott
e990647e1b fix'er'again 2023-10-23 15:09:53 -06:00
Brady McDermott
9079225a29 Update Program-Manager-II-2010.sln
compile...
2023-10-23 15:07:44 -06:00
Brady McDermott
6e4d38544e vista compatibility complete 2023-10-23 14:06:02 -06:00
freedom
5d17a98ca0 vista compatibility, remove pathcch 2023-10-23 13:51:04 -06:00
freedom
bce106ce5f more vista-readiness 2023-10-23 13:46:39 -06:00
Brady McDermott
2b32d3f8f8 brogramming 2023-10-22 13:49:50 -06:00
Brady McDermott
000ecc527f vista+ compatibility part 1 2023-10-21 13:40:47 -06:00
Brady McDermott
e7bcb43cd1 Update .gitignore 2023-10-21 12:56:06 -06:00
Brady McDermott
28e5ec10fc add vs2010 solution and project 2023-10-21 12:55:48 -06:00
Brady McDermott
55ea523d34 Update .gitignore
no .user either
2023-10-21 12:10:19 -06:00
Brady McDermott
52fc4cdcab add suo to gitignore 2023-10-21 12:05:16 -06:00
freedom
1c273f6337 plelaasee 2023-10-19 10:50:44 -06:00
freedom
edd9da0ce4 back on 143 tools, will create new project files later for vs2010 2023-10-18 15:32:00 -06:00
freedom
c9581062f6 idek i'll do it later 2023-10-18 15:31:40 -06:00
Brady McDermott
e0fa6632cd stuff 2023-10-16 14:40:03 -06:00
Brady McDermott
4054dac5f1 balla 2023-10-16 12:19:20 -06:00
freedom
291e1f0d16 load group wip 2023-10-14 16:59:18 -06:00
freedom
97784e31ae save groups 2023-10-13 12:24:05 -06:00
freedom
475d868825 make item batch count a define instead of being as hard-coded 2023-10-13 08:28:33 -06:00
freedom
f718eb4d51 Merge pull request #38 from u130b8/fix-realloc
update pGroup after realloc
2023-10-13 08:21:28 -06:00
freedom
c5c5d6d714 Merge pull request #37 from u130b8/master
Fix build.cmd
2023-10-13 08:16:53 -06:00
u130b8
59f7eb76bd update pGroup after realloc 2023-10-13 13:28:11 +03:00
u130b8
ef8b514527 build with crt for now, add libraries 2023-10-13 13:14:46 +03:00
freedom
39229500f6 fix item dialog not passing the paths 2023-10-13 01:01:38 -06:00
freedom
493abda875 program execution works now just gotta fix the item creation dialog 2023-10-13 00:42:52 -06:00
freedom
1a17c89074 more progress 2023-10-12 22:12:18 -06:00
freedom
bbf9941fd4 almost add double click functionality and execution, add the image list and improve readability when my screen is squished 2023-10-12 14:54:44 -06:00
freedom
012ad25462 coding style 2023-10-12 11:04:54 -06:00
freedom
06e32d9063 possibly solves #34, check again later 2023-10-12 01:47:44 -06:00
freedom
ef0a73d819 temporarily disable the functionality of the program item friendly name finder, will come back to it later but this is how progman did it and it's more reliable atm 2023-10-12 01:40:10 -06:00
freedom
bd4712a7db i am strength 2023-10-12 01:35:54 -06:00
freedom
710fc5aecd more for compile and whatnot, icons appear now 2023-10-12 01:24:00 -06:00
freedom
39ed21c334 vs2019 wants to use v142 build tools, here i'll let it temporarily 2023-10-12 00:52:35 -06:00
freedom
c1e2d5279d idek if this compiled lol image list 2023-10-12 00:50:57 -06:00
freedom7341
ab9e9d9b18 Progress on #17: we have listview with items, beginning context menu implementation, just need to be able to execute the items and then remove groups and items, as well as give icons to all of the items, we are so close!!! 2023-10-11 14:28:01 -06:00
freedom7341
ea0c0773e6 column is unnecessary, remove 2023-10-11 12:24:05 -06:00
freedom7341
efb000f4ec add listview explorer style 2023-10-11 12:23:24 -06:00
freedom7341
36a6d1a888 positions correctly on initialization now 2023-10-11 12:18:18 -06:00
freedom7341
67e821a33c listview works and positions correctly 2023-10-11 12:13:35 -06:00
freedom7341
69a1ea88f5 rename in case of conflict 2023-10-11 11:44:53 -06:00
freedom7341
0c0f9c765e remove unnecessary cast 2023-10-11 11:38:31 -06:00
freedom7341
b8c4a712f9 fix compile complaints 2023-10-11 11:37:07 -06:00
freedom
b07bcbfa6d pain 2023-10-11 11:11:59 -06:00
freedom
531400b700 a step closer now i just need the item.. to appear. 2023-10-11 11:03:24 -06:00
freedom
15d3bcca5c it no longer crashes 2023-10-11 10:49:34 -06:00
freedom7341
fa1ac0dfc9 i wanna work on this on my desktop 2023-10-11 10:17:34 -06:00
freedom7341
14c5e5560b cast 2023-10-10 16:32:25 -06:00
freedom7341
6f312892e8 begin listviewery 2023-10-10 16:31:19 -06:00
freedom7341
1ed794d640 switch L"" to TEXT("") 2023-10-10 16:31:06 -06:00
freedom7341
c43c176538 grup 2023-10-10 13:14:29 -06:00
freedom
fd51e72432 i'll fix this later 2023-10-04 21:00:06 -06:00
freedom
403cfafedb createitem 2023-10-04 14:54:00 -06:00
freedom7341
866402a7b3 item functions 2023-10-04 14:42:16 -06:00
freedom7341
717d744195 really round up 2023-10-04 13:27:22 -06:00
freedom7341
2c16c265ca use pointers instead :D 2023-10-04 13:20:01 -06:00
freedom7341
82c2d2d15f remove unnecessary variable 2023-10-04 13:10:50 -06:00
freedom7341
925bb43a6d fix memory calculation 2023-10-04 13:02:03 -06:00
freedom7341
b02cc93c6d lil issue 2023-10-04 12:37:53 -06:00
freedom7341
e6b36b3b94 accidentally referenced old function name 2023-10-04 12:37:23 -06:00
freedom7341
51e907a7d0 lil correction in a header 2023-10-04 12:34:40 -06:00
freedom7341
6533f53aaa group and memory management stuff 2023-10-04 12:34:33 -06:00
freedom
f2b1af5cba cleanyup 2023-10-02 23:21:56 -06:00
freedom
b14c11f98e pulls the right icon now 2023-10-02 22:29:35 -06:00
freedom7341
99fbc7392c gotte 2023-10-02 16:30:12 -06:00
freedom7341
ab20d2ec8c item dialog icon 2023-10-02 16:25:14 -06:00
freedom7341
678eef08c9 item dialog icon 2023-10-02 16:22:26 -06:00
freedom7341
4269ded2f6 more 2023-10-02 16:17:14 -06:00
freedom7341
44270fd601 fixed name retrieval for files without a description 2023-10-02 14:13:24 -06:00
freedom
c7d3ae27d1 retrieve name from file description, as a backup just input the name of the file, almost got a cool feature here just wip it up a little more, not working properly yet 2023-10-02 13:47:57 -06:00
freedom7341
3245d93436 wip wip wip wip committing so i can get to it from another pc 2023-10-02 12:21:23 -06:00
freedom7341
7e3fcb1fc3 ;ji oua eg uagr iua g 2023-09-29 17:57:55 -06:00
freedom7341
607330267f removed a lil cruft, proper shutdown dialog coming soon i swear please i swear 2023-09-29 17:46:45 -06:00
freedom7341
5d7536d5fd program groups are now.. INVINCIBLE 2023-09-29 17:16:18 -06:00
freedom7341
5e6f59f946 make it compile again 2023-09-28 10:49:42 -06:00
freedom7341
cbb7373cc1 update group format variable names 2023-09-27 13:58:44 -06:00
freedom7341
58e6635bae update group format to account for that \0 2023-09-27 13:39:03 -06:00
freedom7341
b2413ad307 shutdown dialog stuff 2023-09-27 13:37:42 -06:00
freedom7341
49d22b8a13 memory management will happen in a different way :D 2023-09-27 12:22:37 -06:00
freedom7341
d4aa908ea2 begin shutdown dialog and a few other small things, come back to this later 2023-09-27 12:22:01 -06:00
freedom7341
4dfb5d8554 groups coming sooner than expected... or later i guess, i was supposed to have this done 2 weeks ago 2023-09-27 12:21:37 -06:00
freedom7341
2ff4ee0c9c remove unused function 2023-09-27 11:54:08 -06:00
freedom7341
24a17d0287 prep for memory management 2023-09-22 14:17:16 -06:00
freedom7341
6943fc563b desktop rewrite coming soon 2023-09-18 11:13:16 -06:00
freedom7341
b8466d176b some framework for permissions down the line 2023-09-18 10:57:56 -06:00
freedom7341
48c8f542bc work is happening 2023-09-15 11:46:01 -06:00
freedom7341
d16b7254da update file headers and version information 2023-09-14 14:41:25 -06:00
freedom
349a9a9d0d minor cool changes 2023-09-07 14:52:41 -06:00
freedom
2aa96bc024 [DEBUG] 2023-09-07 14:52:13 -06:00
freedom
e0724dc0c7 fix the window menu 2023-09-07 14:52:05 -06:00
freedom
99d851f368 some group changes 2023-09-07 14:25:20 -06:00
freedom
ef30558e0a update debug icon 2023-09-07 14:24:18 -06:00
freedom
1ff398ad70 re-added manifest compatibility info to fix winver reporting 2023-09-07 14:24:10 -06:00
freedom
cbe1fb7551 make it easy to spot pesky debug builds 2023-09-07 04:09:36 -06:00
freedom
1b8ec3b152 Merge pull request #31 from u130b8/master
add older dpi scaling options
2023-09-07 02:38:54 -07:00
u130b8
84f106938d add older dpi scaling options 2023-09-07 12:36:26 +03:00
freedom
f761ac6cf7 Merge pull request #30 from u130b8/master
add hidpi support and simplify manifest (closes #21)
2023-09-07 02:29:34 -07:00
u130b8
3cbe91cf89 Merge branch 'master' of https://github.com/u130b8/Program-Manager-II 2023-09-07 12:20:28 +03:00
freedom
fd3abe1795 Merge branch 'master' of https://github.com/Vortesys/Program-Manager-II 2023-09-07 03:19:37 -06:00
freedom
42f0f268d9 update gitignore to work a lil better 2023-09-07 03:19:32 -06:00
freedom
6ce9166a92 Merge pull request #29 from u130b8/master
build release without crt, build debug with crt
2023-09-07 02:15:36 -07:00
u130b8
e19e3d399b simplify manifest and add hidpi support 2023-09-07 11:14:24 +03:00
u130b8
d7a3802571 use custom defines to prevent vs builds from breaking 2023-09-07 11:11:47 +03:00
u130b8
a074441a99 fix failing build when PROGMGR_GIT_HASH is not defined 2023-09-07 11:06:58 +03:00
u130b8
59937a8690 comment the no_crt situation 2023-09-07 10:59:31 +03:00
u130b8
613b998348 include git hash in build 2023-09-07 10:54:02 +03:00
u130b8
e0461949ae move UNICODE define out of defs 2023-09-07 10:33:12 +03:00
u130b8
acc63b5aa6 rename zipbuild to zip.cmd 2023-09-07 10:32:11 +03:00
u130b8
64d69162ab build release without crt by default, build debug with crt 2023-09-07 10:31:55 +03:00
freedom
6ac03d7a1b more... group... 2023-09-06 06:09:25 -06:00
freedom
0d237c5039 Merge pull request #28 from u130b8/master
make debug build work, remove /NODEFAULTLIB for now
2023-09-06 05:08:35 -07:00
freedom
714fe3a4ae Merge branch 'master' into master 2023-09-06 05:08:23 -07:00
u130b8
5d0a3f1ccf make debug build work, remove /NODEFAULTLIB for now 2023-09-06 15:05:22 +03:00
freedom
d7e5d10209 fix build 2023-09-06 05:41:42 -06:00
freedom
d01b18e035 Merge pull request #27 from u130b8/master
add build.cmd and make it build from command line
2023-09-06 04:37:27 -07:00
freedom
6c40ba9886 ok so now the variables do the needful 2023-09-06 05:23:39 -06:00
u130b8
0d0e37b561 add build.cmd and make it build from command line 2023-09-06 14:16:24 +03:00
freedom
bda528569b i just want groups to work man PLEASe man well listview looks like it works so that's something i guess but now i gotta really add items to it oh my GOD 2023-09-06 04:42:32 -06:00
freedom
9bb0dfd24b better dialoggery 2023-09-06 03:23:44 -06:00
freedom
ef88804240 some more dialogger while i procrastinate listview 2023-09-05 03:36:37 -06:00
freedom
a494e057c9 icon restructure 2023-09-04 21:30:07 -06:00
freedom
7910340133 listviewery? 2023-08-16 21:10:15 -06:00
freedom
b736576829 set filetime 2023-08-16 21:08:04 -06:00
freedom
94f4e71b20 comment correction 2023-08-16 21:07:45 -06:00
freedom
9e67a3d81b mdi tiling for dummys 2023-08-16 03:28:26 -06:00
67 changed files with 1519 additions and 632 deletions

View File

@@ -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

12
.gitignore vendored
View File

@@ -44,17 +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

View File

@@ -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

View File

@@ -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

View File

@@ -1,15 +1,21 @@
![Program Manager II by Vortesys](/misc/progman.jpg)
[![Latest version](https://img.shields.io/github/v/release/Vortesys/Program-Manager-II?label=latest%20version&sort=semver&style=plastic)](https://github.com/Vortesys/Program-Manager-II/releases) [![Latest pre-release version](https://img.shields.io/github/v/release/Vortesys/Program-Manager-II?label=latest%20pre-release%20version&sort=semver&style=plastic&include_prereleases)](https://github.com/Vortesys/Program-Manager-II/releases)
# Program Manager *II* for Windows NT
![Progmgr banner](/misc/pman2.png)
## 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.

BIN
bin.zip Normal file

Binary file not shown.

37
build.cmd Normal file
View 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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

BIN
misc/progman.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@@ -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;
}

View File

@@ -1,6 +1,6 @@
/* * * * * * * *\
DIALOG.C -
Copyright (c) 2023 freedom7341, Vortesys
Copyright (c) 2024 Vortesys, Brady McDermott
DESCRIPTION -
Program Manager's dialogs and related
common functions.
@@ -9,14 +9,21 @@
\* * * * * * * */
/* 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"
// #define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Shlobj.h>
#include <strsafe.h>
/* Variables */
WCHAR szDlgTitle[64];
/* Functions */
@@ -28,22 +35,11 @@
\* * * */
BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
GROUP grp = {
.dwSignature = GRP_SIGNATURE,
.wVersion = GRP_VERSION,
.wChecksum = 0,
.szName = L"",
.dwFlags = 0,
.ftLastWrite = 0,
.cItems = 0,
.iItems = NULL
};
static GROUP grp = { 0 };
BOOL bOKEnabled = FALSE;
WCHAR szBuffer[MAX_TITLE_LENGTH] = { L"\0" };
WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
HICON hIconDef = NULL;
HICON hIconDlg = NULL;
WCHAR szIconPath[MAX_PATH] = { L"\0" };
INT iIconIndex = 0;
switch (message)
{
@@ -54,16 +50,28 @@ BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM
// 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(NULL, (LPWSTR)&szIconPath, MAX_PATH);
iIconIndex = IDI_PROGGRP - 1;
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(hAppInstance, (LPWSTR)&szIconPath, iIconIndex);
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
@@ -72,6 +80,9 @@ BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM
// 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:
@@ -92,22 +103,20 @@ BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM
{
case IDD_CHICON:
if (PickIconDlg(hWndDlg, (LPWSTR)&szIconPath, ARRAYSIZE(szIconPath), &iIconIndex) == TRUE)
if (PickIconDlg(hWndDlg, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath), &grp.iIconIndex) == TRUE)
{
// Since we've got the new icon...
hIconDlg = ExtractIcon(hAppInstance, (LPWSTR)&szIconPath, iIconIndex);
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
bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer));
// If not, set the focus to the offending field
if (!bOKEnabled)
SendDlgItemMessage(hWndDlg, IDD_NAME, EM_TAKEFOCUS, 0, 0);
// 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);
@@ -121,17 +130,14 @@ BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM
if (SendDlgItemMessage(hWndDlg, IDD_COMMGROUP, BM_GETCHECK, 0, 0) != BST_UNCHECKED)
grp.dwFlags = grp.dwFlags || GRP_FLAG_COMMON;
// TODO: set FILETIME
// 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;
// Set icon properties
StringCchCopy(grp.szIconPath, ARRAYSIZE(szIconPath), szIconPath);
grp.iIconIndex = iIconIndex;
// Group's ready!
if (CreateGroupWindow(&grp) != NULL)
if (CreateGroup(&grp) != NULL)
{
EndDialog(hWndDlg, FALSE);
break;
@@ -174,17 +180,253 @@ BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM
\* * * */
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:
// Place message cases here.
// 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;
@@ -194,8 +436,57 @@ BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM l
}
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;
}

View File

@@ -1,6 +1,6 @@
/* * * * * * * *\
DIALOG.H -
Copyright (c) 2023 freedom7341, Vortesys
Copyright (c) 2024 Vortesys, Brady McDermott
DESCRIPTION -
Dialog function prototypes and related
common dialog functions.
@@ -14,3 +14,4 @@
/* 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);

View File

@@ -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,19 +8,24 @@
\* * * * * * * */
/* 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>
#include <strsafe.h>
/* Variables */
WNDCLASSEX wcGrp;
WCHAR szGrpClass[16];
PGROUPWND pgwArray[];
HWND hWndMDIClient = NULL;
HWND hWndFoundGroup = NULL;
/* Functions */
@@ -32,36 +37,40 @@ HWND hWndMDIClient = NULL;
TRUE if groups are successfully created.
FALSE if otherwise.
\* * * */
BOOL InitializeGroups()
BOOL InitializeGroups(VOID)
{
CLIENTCREATESTRUCT ccs = { 0 };
WNDCLASSEX wce = { 0 };
RECT rcFrame;
// Create the MDI Client Window
ccs.hWindowMenu = GetSubMenu(GetMenu(hWndProgMgr), IDM_WINDOW);
ccs.hWindowMenu = GetSubMenu(GetMenu(g_hWndProgMgr), 2);
ccs.idFirstChild = IDM_WINDOW_CHILDSTART;
GetClientRect(hWndProgMgr, &rcFrame);
GetClientRect(g_hWndProgMgr, &rcFrame);
if (!(hWndMDIClient = CreateWindowEx(WS_EX_COMPOSITED, L"MDIClient",
NULL, WS_CLIPCHILDREN | WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
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,
hWndProgMgr, (HMENU)1, hAppInstance, (LPWSTR)&ccs)))
g_hWndProgMgr, (HMENU)1, g_hAppInstance, (LPWSTR)&ccs)) == NULL)
{
return FALSE;
}
// Load the group class string
LoadString(hAppInstance, IDS_GRPCLASS, szGrpClass, ARRAYSIZE(szGrpClass));
LoadString(g_hAppInstance, IDS_GRPCLASS,
szGrpClass, ARRAYSIZE(szGrpClass));
// Register the group window Class
// Register the group window class
wce.cbSize = sizeof(WNDCLASSEX);
wce.style = CS_DBLCLKS;
wce.lpfnWndProc = GroupWndProc;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hInstance = hAppInstance;
wce.hIcon = hGroupIcon = LoadImage(hAppInstance, MAKEINTRESOURCE(IDI_PROGGRP), IMAGE_ICON,
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);
@@ -70,161 +79,491 @@ BOOL InitializeGroups()
if (!RegisterClassEx(&wce))
return FALSE;
// Now we can create the groups
if(LoadConfig(FALSE, FALSE, TRUE) != RCE_SUCCESS)
return FALSE;
// CreateGroupWindow(NULL);
// TODO: if loading groups fails, throw an error
return TRUE;
}
/* * * *\
CreateGroupWindow -
CreateGroup -
Create an MDI window from a group structure
RETURNS -
Pointer to a group window structure
Handle to the new group window
or NULL on failure
\* * * */
PGROUPWND CreateGroupWindow(PGROUP pgGroup)
HWND CreateGroup(_In_ PGROUP pg)
{
GROUPWND gw = { NULL };
MDICREATESTRUCT mcs = { NULL };
HICON hIconBig = NULL;
PGROUP pGroup = NULL;
HICON hIconLarge = NULL;
HICON hIconSmall = NULL;
// Copy group structure to our group window
gw.grp = *pgGroup;
HICON hIconTemp = NULL;
HWND hWndGroup = NULL;
HIMAGELIST hImageList = NULL;
HWND hWndListView = NULL;
RECT rcGroupWindow = { 0 };
LVCOLUMN lvc = { 0 };
// TODO: allocate memory from pgwArray in here
if (pg == NULL)
return NULL;
// TODO: Automatically add itself to the array of
// PGW pointers?
// 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;
// Get group minimized/maximized flags
// 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 = gw.grp.szName;
mcs.hOwner = hAppInstance;
if ((gw.grp.rcGroup.left == CW_USEDEFAULT) & (gw.grp.rcGroup.right == CW_USEDEFAULT))
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;
}
else
{
mcs.x = gw.grp.rcGroup.left;
mcs.y = gw.grp.rcGroup.top;
mcs.cx = gw.grp.rcGroup.right - gw.grp.rcGroup.left;
mcs.cy = gw.grp.rcGroup.bottom - gw.grp.rcGroup.top;
}
mcs.style = WS_VISIBLE;
mcs.lParam = (LPARAM)pgGroup;
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 (!(gw.hWndGroup = (HWND)SendMessage(hWndMDIClient, WM_MDICREATE, 0, (LPARAM)(LPTSTR)&mcs)))
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
ExtractIconEx(gw.grp.szIconPath, gw.grp.iIconIndex, &hIconBig, &hIconSmall, 0);
SendMessage(gw.hWndGroup, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall);
SendMessage(gw.hWndGroup, WM_SETICON, ICON_BIG, (LPARAM)hIconBig);
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!
return &gw;
// AND IMAGE LIST!!!!!!!!? i think it's nuked w/ listview though
return hWndGroup;
}
/* * * *\
SetGroupFlags -
Retrieve the flags of a group window.
RemoveGroup -
Removes and cleans up a group window
RETURNS -
TRUE if the flag mask is applied
FALSE if the flags aren't set
TRUE if cleanup is successful,
FALSE otherwise.
\* * * */
BOOL SetGroupFlags(PGROUPWND pgw, DWORD dwFlags)
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;
}
/* * * *\
GetGroupFlags -
Retrieve the flags of a group window.
ExecuteItem -
Runs a program item
RETURNS -
TRUE if the flag mask is applied
FALSE if the flags aren't set
TRUE if item was successfully ran
FALSE otherwise
\* * * */
BOOL GetGroupFlags(PGROUPWND pgw, DWORD dwFlags)
BOOL ExecuteItem(_In_ PITEM pi)
{
HWND hWndGrp;
// TODO: nCmdShow from program item flags
ShellExecute(g_hWndProgMgr, TEXT("open"),
pi->szExecPath, NULL,
(pi->szWorkPath != TEXT("")) ? pi->szWorkPath : NULL,
SW_NORMAL);
// Cancel if the group window doesn't exist
if (pgw == NULL)
return 0xFFFFFFFF;
// TODO: if item has run as admin as a flag,
// run it as an admin
// Get the window handle
hWndGrp = pgw->hWndGroup;
// TODO: if path is invalid or other error then tell the user
if (hWndGrp != NULL)
{
// NOTE: come back to this lol
// TODO: establish better what this actually does
// min/max flags are pulled from hwnd
// common/readonly flags are set upon group creation
// this means that some flags are static whereas
// others change over time, this means that we can
// either assume certain flags never change over time
// or grab them every time.
return 0xFFFFFFFF;
}
return 0xFFFFFFFF;
// TODO: make sure environment is
// refreshed before execution
return FALSE;
}
/* * * *\
SaveGroup -
Saves group from a group window
into a GROUP structure.
UpdateGroup -
Updates group information to prepare
it for being saved.
ABSTRACT -
This function will extract all of the
necessary information from a group window
in order to produce a group structure.
This function will update all of the
relevant structures in a group struct
in preparation for saving the group.
RETURNS -
Formatted GROUP structure.
Upon failure, wChecksum will be 0.
Nothing.
\* * * */
GROUP SaveGroup(PGROUPWND pgw)
VOID UpdateGroup(_In_ PGROUP pg)
{
GROUP grp = {
.dwSignature = GRP_SIGNATURE,
.wVersion = GRP_VERSION,
.wChecksum = 0,
.szName = L"",
.dwFlags = 0,
.ftLastWrite = 0,
.cItems = 0,
.iItems = NULL
};
HWND hWndGrp;
WCHAR szGroupName[MAX_TITLE_LENGTH];
DWORD dwFlags = 0;
HWND hWndGroup = NULL;
// Find the group and copy it
grp = pgw->grp;
// Get the window handle as well
hWndGrp = pgw->hWndGroup;
// Set the important flags
pg->dwSignature = GRP_SIGNATURE;
pg->wVersion = GRP_VERSION;
// Set the group checksum
grp.wChecksum = 1; // NOTE: implement this for real later lol
pg->wChecksum = 1; // NOTE: implement this for real later lol
// Copy group information
GetWindowText(hWndGrp, szGroupName, MAX_TITLE_LENGTH);
StringCchCopy(grp.szName, MAX_TITLE_LENGTH, szGroupName);
// TODO: group flags
// pg->dwFlags = GRP_FLAG_MAXIMIZED;// GetGroupFlags(pgw);
grp.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));
}
GetSystemTimeAsFileTime(&grp.ftLastWrite);
return;
}
// Save items...
grp.cItems = 0;
// TODO: iterate through listview to save items
/* * * *\
GetHwndFromPGroup -
In goes a PGROUP out comes a HWND
RETURNS -
HWND.
\* * * */
HWND GetHwndFromPGroup(_In_ PGROUP pg)
{
EnumChildWindows(g_hWndProgMgr, (WNDENUMPROC)GetHwndFromPGroupEnum, (LPARAM)pg);
return grp;
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;
}
/* * * *\
@@ -235,15 +574,181 @@ GROUP SaveGroup(PGROUPWND pgw)
\* * * */
LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
break;
}
default:
// GroupProcDefault:
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:
break;
}
return DefMDIChildProc(hWnd, message, wParam, lParam);
}
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);
}
/* * * *\
GroupCmdProc -
Group syscommand procedure.
RETURNS -
Zero if nothing, otherwise returns the good stuff.
\* * * */
LRESULT CALLBACK GroupCmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDM_FILE_OPEN:
{
HWND hWndListView = NULL;
LVITEM lvi = { 0 };
PITEM pItem = NULL;
// find the listview control
hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL);
if (hWndListView == NULL)
break;
// 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;
}

View File

@@ -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 -
@@ -13,18 +13,21 @@
/* 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 1 // Increment for breaking changes
#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_MINIMIZED 0x00000001
#define ITM_FLAG_MAXIMIZED 0x00000002
#define ITM_FLAG_HOTKEY 0x00000001
#define ITM_FLAG_PRIVILEGE 0x00000002
#define ITM_FLAG_MINIMIZED 0x00000004
#define ITM_FLAG_MAXIMIZED 0x00000008
/* Structures */
// Item Structure
@@ -54,35 +57,37 @@ typedef struct _GROUP {
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 {
// Windows
HWND hWndGroup;
HWND hWndListView;
// Group
GROUP grp; // Pointer to GROUP structure
} GROUPWND, * PGROUPWND;
/* Global Variables */
extern HWND hWndMDIClient;
/* Local Variables */
/* Function Prototypes */
BOOL InitializeGroups();
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);
PGROUPWND CreateGroupWindow(PGROUP pgGroup);
// Group information
BOOL SetGroupFlags(PGROUPWND pgw, DWORD dwFlags);
BOOL GetGroupFlags(PGROUPWND pgw, DWORD dwFlags);
// Import/export functions
GROUP SaveGroup(PGROUPWND pgw);
LRESULT CALLBACK GroupCmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam);

View File

@@ -1,6 +1,6 @@
/* * * * * * * *\
GRPUPDAT.H -
Copyright (c) 2023 freedom7341, Vortesys
Copyright (c) 2024 Vortesys, Brady McDermott
DESCRIPTION -
Header containing classic program group structures
in order to facilitate conversion to the new format.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
progmgr/icons/progmgrd.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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;
#ifdef _DEBUG
BOOL g_bIsDebugBuild = TRUE;
#else
BOOL g_bIsDebugBuild = FALSE;
#endif
BOOL g_bIsDefaultShell = FALSE;
// Handles
HINSTANCE hAppInstance;
HANDLE hAppHeap;
HWND hWndProgMgr = NULL;
HINSTANCE g_hAppInstance;
HWND g_hWndProgMgr = NULL;
// Icons
HICON hProgMgrIcon = NULL;
HICON hGroupIcon = NULL;
HICON g_hProgMgrIcon = NULL;
HICON g_hGroupIcon = NULL;
// Global Strings
WCHAR szAppTitle[32];
WCHAR szProgMgr[] = L"progmgr";
WCHAR szWebsite[64];
WCHAR szClass[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,41 +69,49 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
HANDLE hAccel;
HMENU hMenu;
HMENU hSystemMenu;
HWND hOldProgMgr;
WNDCLASS wc = { 0 };
WCHAR szBuffer[MAX_PATH];
RECT rcRoot;
POINT ptOffset;
POINT ptOffset = { 0 };
// Initialize the instance
hAppInstance = hInstance;
// Create our global heap handle
hAppHeap = GetProcessHeap();
// Grab the instance
g_hAppInstance = hInstance;
// Create Strings
LoadString(hAppInstance, IDS_PMCLASS, szClass, ARRAYSIZE(szClass));
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;
// Load the Accelerator table
hAccel = LoadAccelerators(hAppInstance, MAKEINTRESOURCE(IDA_ACCELS));
hAccel = LoadAccelerators(g_hAppInstance, MAKEINTRESOURCE(IDA_ACCELS));
if (!hAccel)
return FALSE;
@@ -86,7 +119,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
if (!InitializeRegistryKeys())
return FALSE;
bIsDefaultShell = IsProgMgrDefaultShell();
g_bIsDefaultShell = IsProgMgrDefaultShell();
// Load configuration, but don't load groups yet
if(LoadConfig(TRUE, TRUE, FALSE) != RCE_SUCCESS)
@@ -101,22 +134,23 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
// Create main window with a default size
// TODO: i pulled 320x240 out of my ass, make this dynamic later
if (!(hWndProgMgr = CreateWindowW(wc.lpszClassName, szAppTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
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);
@@ -129,21 +163,21 @@ 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...
@@ -157,7 +191,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
if (!TranslateMDISysAccel(hWndMDIClient, &msg) &&
!TranslateAccelerator(hWndProgMgr, hAccel, &msg))
!TranslateAccelerator(g_hWndProgMgr, hAccel, &msg))
{
DispatchMessage(&msg);
}
@@ -165,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
*/

View File

@@ -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>

View File

@@ -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,23 +31,25 @@
#define RF_RETRY 0x0002 // Cancel the operation, but leave the dialog open
/* Global Variables */
extern BOOL bIsDefaultShell;
extern BOOL g_bIsDefaultShell;
// Handles
extern HINSTANCE hAppInstance;
extern HANDLE hAppHeap;
extern HWND hWndProgMgr;
extern HINSTANCE g_hAppInstance;
extern HWND g_hWndProgMgr;
// Icons
extern HICON hProgMgrIcon;
extern HICON hGroupIcon;
extern HICON g_hProgMgrIcon;
extern HICON g_hGroupIcon;
// Strings
extern WCHAR szAppTitle[32];
extern WCHAR szProgMgr[];
extern WCHAR szWebsite[64];
extern WCHAR szClass[16];
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);
@@ -54,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);

View File

@@ -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>
@@ -167,7 +177,6 @@
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="desktop.c" />
<ClCompile Include="dialog.c" />
<ClCompile Include="progmgr.c" />
<ClCompile Include="registry.c" />

View File

@@ -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">
@@ -44,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>
@@ -64,11 +64,11 @@
<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>

View File

@@ -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>

View File

@@ -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,13 +8,13 @@
\* * * * * * * */
/* Headers */
#include "progmgr.h"
#include "group.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
@@ -36,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 */
@@ -51,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;
@@ -74,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);
@@ -112,48 +113,44 @@ BOOL IsProgMgrDefaultShell()
}
/* * * *\
SaveGroupToRegistry -
Saves a group structure to registry.
RegistrySaveGroup -
Saves a group structure to the registry.
RETURNS -
RCE_* configuration error value
\* * * */
DWORD SaveGroupToRegistry(_In_ PGROUP pg)
DWORD RegistrySaveGroup(_In_ PGROUP pg)
{
DWORD dwConfigStatus = RCE_SUCCESS;
// If the pointer is invalid then fail out
if (pg == NULL)
// 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) + sizeof(ITEM) * pg->cItems)) == ERROR_SUCCESS)
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
(const BYTE*)pg, sizeof(*pg)) == ERROR_SUCCESS)
return RCE_GROUPS;
return dwConfigStatus;
return RCE_SUCCESS;
}
/* * * *\
LoadGroupFromRegistry -
Loads a group structure from the registry.
RegistryRemoveGroup -
Removes a group structure from the registry.
RETURNS -
RCE_* configuration error value
\* * * */
DWORD LoadGroupFromRegistry(_Inout_ PGROUP pg, _Out_ DWORD dwBufferSize)
DWORD RegistryRemoveGroup(_In_ PGROUP pg)
{
DWORD dwConfigStatus = RCE_SUCCESS;
DWORD dwType = REG_BINARY;
// If the pointer is invalid then fail out
if (pg == NULL)
// If the pointer or HKEY is invalid then fail out
if ((pg == NULL) || (hKeyProgramGroups == NULL))
return RCE_FAILURE;
// Load group
if (!RegQueryValueEx(hKeyProgramGroups, pg->szName, 0, &dwType,
(LPBYTE)pg, &dwBufferSize) == ERROR_SUCCESS)
dwConfigStatus = dwConfigStatus && RCE_POSITION;
// 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 dwConfigStatus;
return RCE_SUCCESS;
}
/* * * *\
@@ -163,7 +160,7 @@ DWORD LoadGroupFromRegistry(_Inout_ PGROUP pg, _Out_ DWORD dwBufferSize)
RETURNS -
RCE_* configuration error value
\* * * */
DWORD SaveConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
DWORD SaveConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups, _In_ BOOL bExit)
{
DWORD dwConfigStatus = RCE_SUCCESS;
@@ -186,12 +183,12 @@ DWORD SaveConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
if (bPos)
{
WINDOWPLACEMENT wpProgMgr;
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,
@@ -201,15 +198,61 @@ DWORD SaveConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
if (bGroups)
{
// TODO: Get list of groups, iterate through,
// save each one as an individual subkey based
// on the name of the group
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
HWND hWndGroup = NULL;
EnumChildWindows(hWndMDIClient, &SaveWindowEnumProc, (LPARAM)bExit);
}
return dwConfigStatus;
}
/* * * *\
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
@@ -217,7 +260,7 @@ DWORD SaveConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
RETURNS -
RCE_* configuration error value
\* * * */
DWORD LoadConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
DWORD LoadConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups)
{
DWORD dwConfigStatus = RCE_SUCCESS;
@@ -252,8 +295,111 @@ DWORD LoadConfig(BOOL bSettings, BOOL bPos, BOOL bGroups)
if (bGroups)
{
// TODO: this is unbearable
dwConfigStatus = dwConfigStatus && RCE_GROUPS;
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;

View File

@@ -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,16 +10,13 @@
/* 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"
#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
@@ -50,8 +47,10 @@ extern RECT rcMainWindow;
BOOL InitializeRegistryKeys(VOID);
BOOL IsProgMgrDefaultShell(VOID);
// Groups
DWORD SaveGroupToRegistry(_In_ PGROUP pg);
DWORD LoadGroupFromRegistry(_Inout_ PGROUP pg, _Out_ DWORD dwBufferSize);
DWORD RegistrySaveGroup(_In_ PGROUP pg);
DWORD RegistryRemoveGroup(_In_ PGROUP pg);
// Settings
DWORD SaveConfig(BOOL bSettings, BOOL bPos, BOOL bGroups);
DWORD LoadConfig(BOOL bSettings, BOOL bPos, BOOL bGroups);
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);

Binary file not shown.

View File

@@ -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
@@ -21,16 +21,22 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/* 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"
@@ -39,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

View File

@@ -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)
{

Binary file not shown.

View File

@@ -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,17 +8,19 @@
\* * * * * * * */
/* Headers */
#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"
// #define WIN32_LEAN_AND_MEAN
#define SECURITY_WIN32
#include <Windows.h>
#include <strsafe.h>
#include <Lmcons.h>
#include <security.h>
/* Functions */
@@ -35,7 +37,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_CREATE:
{
break;
// 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:
@@ -44,7 +50,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (wParam == IDM_TASKMGR)
{
ShellExecute(hWndProgMgr, L"open", L"TASKMGR.EXE", NULL, NULL, SW_NORMAL);
ShellExecute(g_hWndProgMgr, TEXT("open"), TEXT("TASKMGR.EXE"), NULL, NULL, SW_NORMAL);
return 0;
}
@@ -52,31 +58,27 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
goto WndProcDefault;
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
}
case WM_COMMAND:
if (CmdProc(hWnd, wParam, lParam))
return 0;
goto WndProcDefault;
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
case WM_CLOSE:
case WM_ENDSESSION:
if (bSaveSettings)
SaveConfig(TRUE, TRUE, TRUE);
SaveConfig(TRUE, TRUE, TRUE, TRUE);
if (bIsDefaultShell && (GetShellWindow() != NULL))
if (g_bIsDefaultShell && (GetShellWindow() != NULL))
SetShellWindow(0);
PostQuitMessage(0);
break;
case WM_ENDSESSION:
PostQuitMessage(0);
break;
default:
WndProcDefault:
return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam);
}
return 0;
@@ -95,15 +97,23 @@ 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(hAppInstance, MAKEINTRESOURCE(DLG_GROUP), hWnd, (DLGPROC)NewGroupDlgProc);
DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_GROUP), hWnd, (DLGPROC)NewGroupDlgProc);
break;
case IDM_FILE_NEW_ITEM:
DialogBox(hAppInstance, MAKEINTRESOURCE(DLG_ITEM), hWnd, (DLGPROC)NewItemDlgProc);
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:
@@ -126,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;
@@ -143,23 +153,51 @@ LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam)
case IDM_OPTIONS_SAVENOW:
SaveConfig:
SaveConfig(TRUE, TRUE, TRUE);
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;
}
@@ -176,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;
@@ -189,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;
}