From cc62e8dc3823f309b348fd98aa984c6d8259300d Mon Sep 17 00:00:00 2001 From: Brady McDermott Date: Sun, 20 Oct 2024 21:18:14 -0600 Subject: [PATCH] rename dir 1 --- PROGMGR2/dialog.c | 492 ++++++++++++++++++++++ PROGMGR2/dialog.h | 17 + PROGMGR2/group.c | 677 ++++++++++++++++++++++++++++++ PROGMGR2/group.h | 92 ++++ PROGMGR2/grpupdat.h | 38 ++ PROGMGR2/icons/common.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/bkgsrc.pdn | Bin 0 -> 16946 bytes PROGMGR2/icons/misc/bkgsrctxt.pdn | Bin 0 -> 32165 bytes PROGMGR2/icons/misc/comms.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/console.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/console.pdn | Bin 0 -> 3960 bytes PROGMGR2/icons/misc/data.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/document.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/msdos.ico | Bin 0 -> 1086 bytes PROGMGR2/icons/misc/pmcomm.pdn | Bin 0 -> 4165 bytes PROGMGR2/icons/misc/pmdata.pdn | Bin 0 -> 4015 bytes PROGMGR2/icons/misc/pmlogo.pdn | Bin 0 -> 29585 bytes PROGMGR2/icons/misc/pmsheet.pdn | Bin 0 -> 3935 bytes PROGMGR2/icons/misc/pmword.pdn | Bin 0 -> 3928 bytes PROGMGR2/icons/misc/spsheet.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/superman.ico | Bin 0 -> 766 bytes PROGMGR2/icons/misc/wfdir.pdn | Bin 0 -> 3971 bytes PROGMGR2/icons/misc/wftrdir.pdn | Bin 0 -> 4142 bytes PROGMGR2/icons/misc/wftree.pdn | Bin 0 -> 4054 bytes PROGMGR2/icons/misc/winoldap.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/misc/winoldap.pdn | Bin 0 -> 4003 bytes PROGMGR2/icons/personal.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/pmgroup.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/pmitem.ico | Bin 0 -> 1078 bytes PROGMGR2/icons/progmgr.ico | Bin 0 -> 5414 bytes PROGMGR2/icons/progmgrd.ico | Bin 0 -> 5414 bytes PROGMGR2/icons/src/common.pdn | Bin 0 -> 4249 bytes PROGMGR2/icons/src/personal.pdn | Bin 0 -> 4289 bytes PROGMGR2/icons/src/pmgroup.pdn | Bin 0 -> 4191 bytes PROGMGR2/icons/src/pmitem.pdn | Bin 0 -> 3864 bytes PROGMGR2/icons/src/progmgr.ico | Bin 0 -> 5414 bytes PROGMGR2/icons/src/progmgr.pdn | Bin 0 -> 6614 bytes PROGMGR2/icons/src/progmgrd.ico | Bin 0 -> 5414 bytes PROGMGR2/icons/src/progmgrd.pdn | Bin 0 -> 6457 bytes PROGMGR2/lang/dlg_en-US.rc | 93 ++++ PROGMGR2/lang/res_en-US.rc | 160 +++++++ PROGMGR2/progmgr.c | 221 ++++++++++ PROGMGR2/progmgr.exe.manifest | 28 ++ PROGMGR2/progmgr.h | 61 +++ PROGMGR2/progmgr.vcxproj | 201 +++++++++ PROGMGR2/progmgr.vcxproj.filters | 84 ++++ PROGMGR2/registry.c | 388 +++++++++++++++++ PROGMGR2/registry.h | 55 +++ PROGMGR2/resource.h | 134 ++++++ PROGMGR2/resource.rc | 78 ++++ PROGMGR2/sysint.c | 88 ++++ PROGMGR2/version.inc | Bin 0 -> 1628 bytes PROGMGR2/wndproc.c | 243 +++++++++++ 53 files changed, 3150 insertions(+) create mode 100644 PROGMGR2/dialog.c create mode 100644 PROGMGR2/dialog.h create mode 100644 PROGMGR2/group.c create mode 100644 PROGMGR2/group.h create mode 100644 PROGMGR2/grpupdat.h create mode 100644 PROGMGR2/icons/common.ico create mode 100644 PROGMGR2/icons/misc/bkgsrc.pdn create mode 100644 PROGMGR2/icons/misc/bkgsrctxt.pdn create mode 100644 PROGMGR2/icons/misc/comms.ico create mode 100644 PROGMGR2/icons/misc/console.ico create mode 100644 PROGMGR2/icons/misc/console.pdn create mode 100644 PROGMGR2/icons/misc/data.ico create mode 100644 PROGMGR2/icons/misc/document.ico create mode 100644 PROGMGR2/icons/misc/msdos.ico create mode 100644 PROGMGR2/icons/misc/pmcomm.pdn create mode 100644 PROGMGR2/icons/misc/pmdata.pdn create mode 100644 PROGMGR2/icons/misc/pmlogo.pdn create mode 100644 PROGMGR2/icons/misc/pmsheet.pdn create mode 100644 PROGMGR2/icons/misc/pmword.pdn create mode 100644 PROGMGR2/icons/misc/spsheet.ico create mode 100644 PROGMGR2/icons/misc/superman.ico create mode 100644 PROGMGR2/icons/misc/wfdir.pdn create mode 100644 PROGMGR2/icons/misc/wftrdir.pdn create mode 100644 PROGMGR2/icons/misc/wftree.pdn create mode 100644 PROGMGR2/icons/misc/winoldap.ico create mode 100644 PROGMGR2/icons/misc/winoldap.pdn create mode 100644 PROGMGR2/icons/personal.ico create mode 100644 PROGMGR2/icons/pmgroup.ico create mode 100644 PROGMGR2/icons/pmitem.ico create mode 100644 PROGMGR2/icons/progmgr.ico create mode 100644 PROGMGR2/icons/progmgrd.ico create mode 100644 PROGMGR2/icons/src/common.pdn create mode 100644 PROGMGR2/icons/src/personal.pdn create mode 100644 PROGMGR2/icons/src/pmgroup.pdn create mode 100644 PROGMGR2/icons/src/pmitem.pdn create mode 100644 PROGMGR2/icons/src/progmgr.ico create mode 100644 PROGMGR2/icons/src/progmgr.pdn create mode 100644 PROGMGR2/icons/src/progmgrd.ico create mode 100644 PROGMGR2/icons/src/progmgrd.pdn create mode 100644 PROGMGR2/lang/dlg_en-US.rc create mode 100644 PROGMGR2/lang/res_en-US.rc create mode 100644 PROGMGR2/progmgr.c create mode 100644 PROGMGR2/progmgr.exe.manifest create mode 100644 PROGMGR2/progmgr.h create mode 100644 PROGMGR2/progmgr.vcxproj create mode 100644 PROGMGR2/progmgr.vcxproj.filters create mode 100644 PROGMGR2/registry.c create mode 100644 PROGMGR2/registry.h create mode 100644 PROGMGR2/resource.h create mode 100644 PROGMGR2/resource.rc create mode 100644 PROGMGR2/sysint.c create mode 100644 PROGMGR2/version.inc create mode 100644 PROGMGR2/wndproc.c diff --git a/PROGMGR2/dialog.c b/PROGMGR2/dialog.c new file mode 100644 index 0000000..2b3752c --- /dev/null +++ b/PROGMGR2/dialog.c @@ -0,0 +1,492 @@ +/* * * * * * * *\ + DIALOG.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's dialogs and related + common functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include "progmgr.h" +#include "dialog.h" +#include "group.h" +#include "resource.h" + +/* Variables */ +WCHAR szDlgTitle[64]; + +/* Functions */ + +/* * * *\ + NewGroupDlgProc - + Dialog procedure for creating a group. + RETURNS - + TRUE if message is handled, FALSE otherwise. +\* * * */ +BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static GROUP grp = { 0 }; + BOOL bOKEnabled = FALSE; + WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") }; + HICON hIconDef = NULL; + HICON hIconDlg = NULL; + + switch (message) + { + + case WM_INITDIALOG: + // TODO: + // Enable creation of common groups (enable the controls) + // if permissions are available. + // TODO: + // fix minor GDI font/region leak + + // Reset the necessary parts of the group structure + grp.dwSignature = GRP_SIGNATURE; + grp.wVersion = GRP_VERSION; + grp.wChecksum = 0; + grp.dwFlags = 0; + grp.cItemArray = 0; + // grp.pItemArray = 0; TODO: idk make sure this ain't all screwed up + + // Set the window title + LoadString(g_hAppInstance, IDS_DLT_GRP_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle)); + SetWindowText(hWndDlg, szDlgTitle); + + // Populate the icon with the default path and index. + GetModuleFileName(g_hAppInstance, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath)); + grp.iIconIndex = IDI_PROGGRP - 1; + + // Get the default hIcon so we can delete it later + hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0); + + // Set the icon in the dialog + hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex); + SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0); + + // Set the maximum input length of the text boxes + SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0); + + // Disable the OK button since we're starting with no text in the box. + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + + // Enable the common group checkbox if perms are good + EnableWindow(GetDlgItem(hWndDlg, IDD_COMMGROUP), g_bPermAdmin); + + break; + + case WM_COMMAND: + + if (HIWORD(wParam) == EN_CHANGE) + { + if (LOWORD(wParam) == IDD_NAME) + { + // Name text control changed. See what's up... + bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer)); + + // Enable or disable the OK button based on the information + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + } + } + + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + + case IDD_CHICON: + if (PickIconDlg(hWndDlg, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath), &grp.iIconIndex) == TRUE) + { + // Since we've got the new icon... + hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex); + SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0); + } + + break; + + case IDD_OK: + // Check that all the applicable fields are filled out, + // and if not then set the focus to the offending field + if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer)))) + SetFocus(GetDlgItem(hWndDlg, IDD_NAME)); + + // Enable or disable the OK button based on the information + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + + if (bOKEnabled) + { + // Set the name of the group + StringCchCopy(grp.szName, ARRAYSIZE(szBuffer), szBuffer); + + // Set the flags of the group + if (SendDlgItemMessage(hWndDlg, IDD_COMMGROUP, BM_GETCHECK, 0, 0) != BST_UNCHECKED) + grp.dwFlags = grp.dwFlags || GRP_FLAG_COMMON; + + // Set FILETIME + GetSystemTimeAsFileTime(&grp.ftLastWrite); + + // Set the rectangle of the group to be CW_USEDEFAULT + grp.rcGroup.left = grp.rcGroup.top = grp.rcGroup.right = grp.rcGroup.bottom = CW_USEDEFAULT; + + // Group's ready! + if (CreateGroup(&grp) != NULL) + { + EndDialog(hWndDlg, FALSE); + break; + } + + // Failure! + EndDialog(hWndDlg, FALSE); + break; + } + + break; + + case IDD_CANCEL: + EndDialog(hWndDlg, FALSE); + break; + + default: + break; + } + + default: + // Cleanup + if (hIconDef) + DestroyIcon(hIconDef); + if (hIconDlg) + DestroyIcon(hIconDlg); + + return FALSE; + } + + return TRUE; +} + +/* * * *\ + NewItemDlgProc - + Dialog procedure for creating or modifying + an item. + RETURNS - + TRUE if message is handled, FALSE otherwise. +\* * * */ +BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + static ITEM itm = { 0 }; + BOOL bOKEnabled = FALSE; + BOOL bWorkPath = FALSE; + WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") }; + WCHAR szPathBuffer[MAX_PATH] = { TEXT("\0") }; + HICON hIconDef = NULL; + HICON hIconDlg = NULL; + + switch (message) + { + + case WM_INITDIALOG: + // TODO: + // require a valid group to be selected or else the dialog won't + // EVEN BE AVAILABLE!!! or let you press ok. + + // Reset the necessary parts of the item structure + itm.dwFlags = 0; + itm.uiHotkeyModifiers = 0; + itm.uiHotkeyVirtualKey = 0; + + // Set the window title + LoadString(g_hAppInstance, IDS_DLT_ITEM_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle)); + SetWindowText(hWndDlg, szDlgTitle); + + // Populate the icon with the default path and index. + GetModuleFileName(NULL, (LPWSTR)&itm.szIconPath, MAX_PATH); + itm.iIconIndex = IDI_PROGITM - 1; + + // Get the default hIcon so we can delete it later + hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0); + + // Set the icon in the dialog + hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&itm.szIconPath, itm.iIconIndex); + SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0); + + // Set the maximum input length of the text boxes + SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0); + SendDlgItemMessage(hWndDlg, IDD_PATH, EM_LIMITTEXT, MAX_PATH, 0); + SendDlgItemMessage(hWndDlg, IDD_WORKPATH, EM_LIMITTEXT, MAX_PATH, 0); + + // Disable the OK button since we're starting with no text in the box. + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + + break; + + case WM_COMMAND: + if (HIWORD(wParam) == EN_CHANGE) + { + if ((LOWORD(wParam) == IDD_NAME) || (LOWORD(wParam) == IDD_PATH) || (LOWORD(wParam) == IDD_WORKPATH)) + { + // A control has changed. See what's up... + bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer)); + bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + + if (bWorkPath) + bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + + // Check that we have selected an MDI child window as well + if ((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, FALSE) == (HWND)NULL) + bOKEnabled = FALSE; + + // Enable or disable the relevant controls based on the information + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + } + } + + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + + case IDD_BROWSE: + { + OPENFILENAME ofn; + LPVOID lpData; + DWORD dwVerBuffer = 0; + UINT uiTitleLen = MAX_TITLE_LENGTH; + WCHAR szNameBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") }; + WCHAR szFileBuffer[MAX_PATH] = { TEXT("\0") }; + + GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer, ARRAYSIZE(szFileBuffer)); + + // Initialize the structure + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWndDlg; + ofn.lpstrFilter = TEXT("Programs\0*.exe;*.bat;*.com;*.cmd;*.lnk\0All Files (*.*)\0*.*\0"); + ofn.nFilterIndex = 1; + ofn.lpstrFile = (LPWSTR)&szFileBuffer; + // ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = ARRAYSIZE(szFileBuffer); + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_FILEMUSTEXIST; + + if (GetOpenFileName(&ofn) == TRUE) + SetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer); + else + break; + + // copy the filename to a new buffer for later + StringCchCopy(szNameBuffer, ARRAYSIZE(szNameBuffer), szFileBuffer); + + // let's retrieve the application's friendly name too + dwVerBuffer = GetFileVersionInfoSize((LPCWSTR)szFileBuffer, NULL); + // if (dwVerBuffer != 0) + if (NULL) + { + lpData = malloc(dwVerBuffer); + // TODO: totally redo this it doesn't work + + if (lpData != NULL) + GetFileVersionInfo((LPCWSTR)szFileBuffer, (DWORD)0, dwVerBuffer, lpData); + else + break; + + // TODO: this is hardcoded to english. make it dynamic later + // TODO: this is so busted lol, really make it dynamic so it works + VerQueryValue(lpData, + TEXT("\\StringFileInfo\\040904b0\\FileDescription"), + (LPVOID)&szNameBuffer, &uiTitleLen); // == 0 + + if (lpData) + free(lpData); + } + else + { + PathStripPath((LPWSTR)&szNameBuffer); + PathRemoveExtension((LPWSTR)&szNameBuffer); + } + + SetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)szNameBuffer); + + // let's get the icon now + if (ExtractIcon(g_hAppInstance, (LPWSTR)szFileBuffer, -1) > 0) + { + // file contains at least one icon, set the itm struct values + StringCchCopy(itm.szIconPath, ARRAYSIZE(itm.szIconPath), szFileBuffer); + itm.iIconIndex = 0; + + // update icon + hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex); + SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0); + } + + break; + } + + case IDD_BROWSE2: + { + OPENFILENAME ofn; + + GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + + // Initialize the structure + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWndDlg; + ofn.lpstrFilter = TEXT("Folders\0"); + ofn.nFilterIndex = 1; + ofn.lpstrFile = (LPWSTR)&szPathBuffer; + // ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = ARRAYSIZE(szPathBuffer); + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_FILEMUSTEXIST; + + if (GetOpenFileName(&ofn) == TRUE) { + SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer); + } + + break; + } + + + case IDD_CHICON: + if (PickIconDlg(hWndDlg, (LPWSTR)&itm.szIconPath, ARRAYSIZE(itm.szIconPath), &itm.iIconIndex) == TRUE) + { + // Since we've got the new icon... + hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex); + SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0); + } + + break; + + case IDD_WORKDIR: + bWorkPath = IsDlgButtonChecked(hWndDlg, IDD_WORKDIR); + + if (bWorkPath) + { + GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + PathRemoveFileSpec((LPWSTR)&szPathBuffer); + SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer); + } + else + { + SetWindowText(GetDlgItem(hWndDlg, IDD_WORKPATH), 0); + } + + EnableWindow(GetDlgItem(hWndDlg, IDD_STAT_WORKDIR), bWorkPath); + EnableWindow(GetDlgItem(hWndDlg, IDD_WORKPATH), bWorkPath); + EnableWindow(GetDlgItem(hWndDlg, IDD_BROWSE2), bWorkPath); + + break; + + case IDD_OK: + // Check that all the applicable fields are filled out, + // and if not then set the focus to the offending field + if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer)))) + SetFocus(GetDlgItem(hWndDlg, IDD_NAME)); + if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)))) + SetFocus(GetDlgItem(hWndDlg, IDD_PATH)); + if (bWorkPath) + { + if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)))) + SetFocus(GetDlgItem(hWndDlg, IDD_WORKPATH)); + } + + // Enable or disable the OK button based on the information + EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled); + + if (bOKEnabled) + { + // Set the name of the item + StringCchCopy(itm.szName, ARRAYSIZE(szBuffer), szBuffer); + + // And the paths... + GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + StringCchCopy(itm.szExecPath, ARRAYSIZE(szPathBuffer), szPathBuffer); + GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer)); + StringCchCopy(itm.szWorkPath, ARRAYSIZE(szPathBuffer), szPathBuffer); + + // Item's ready! + if (CreateItem((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, 0), &itm) != NULL) + { + EndDialog(hWndDlg, FALSE); + break; + } + + // Failure! + EndDialog(hWndDlg, FALSE); + break; + } + + break; + + case IDD_CANCEL: + EndDialog(hWndDlg, FALSE); + break; + + default: + break; + } + + default: + // Cleanup + if (hIconDef) + DestroyIcon(hIconDef); + if (hIconDlg) + DestroyIcon(hIconDlg); + + return FALSE; + } + + return TRUE; +} + +/* * * *\ + ShutdownDlgProc - + Dialog procedure for powering off the computer. + RETURNS - + TRUE if message is handled, FALSE otherwise. +\* * * */ +BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HICON hIconDlg = NULL; + + switch (message) + { + + case WM_INITDIALOG: + break; + + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + + case IDD_OK: + { + } + + case IDD_CANCEL: + EndDialog(hWndDlg, FALSE); + break; + + default: + break; + } + break; + + default: + // Cleanup + if (hIconDlg) + DestroyIcon(hIconDlg); + + return FALSE; + } + return TRUE; +} diff --git a/PROGMGR2/dialog.h b/PROGMGR2/dialog.h new file mode 100644 index 0000000..cc3a7a3 --- /dev/null +++ b/PROGMGR2/dialog.h @@ -0,0 +1,17 @@ +/* * * * * * * *\ + DIALOG.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Dialog function prototypes and related + common dialog functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#pragma once + +/* Function Prototypes */ +BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam); diff --git a/PROGMGR2/group.c b/PROGMGR2/group.c new file mode 100644 index 0000000..3edf722 --- /dev/null +++ b/PROGMGR2/group.c @@ -0,0 +1,677 @@ +/* * * * * * * *\ + GROUP.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Group window and program group/item functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include "progmgr.h" +#include "group.h" +#include "resource.h" +#include "registry.h" + +/* Variables */ +WNDCLASSEX wcGrp; +WCHAR szGrpClass[16]; +HWND hWndMDIClient = NULL; +HWND hWndFoundGroup = NULL; + +/* Functions */ + +/* * * *\ + InitializeGroups - + Create the MDI Client window and initialize + the group window class. + RETURNS - + TRUE if groups are successfully created. + FALSE if otherwise. +\* * * */ +BOOL InitializeGroups(VOID) +{ + CLIENTCREATESTRUCT ccs = { 0 }; + WNDCLASSEX wce = { 0 }; + RECT rcFrame; + + // Create the MDI Client Window + ccs.hWindowMenu = GetSubMenu(GetMenu(g_hWndProgMgr), 2); + ccs.idFirstChild = IDM_WINDOW_CHILDSTART; + + GetClientRect(g_hWndProgMgr, &rcFrame); + + if ((hWndMDIClient = CreateWindowEx(WS_EX_COMPOSITED, + TEXT("MDIClient"), NULL, WS_CLIPCHILDREN | WS_CHILD | + WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, + rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom, + g_hWndProgMgr, (HMENU)1, g_hAppInstance, (LPWSTR)&ccs)) == NULL) + { + return FALSE; + } + + // Load the group class string + LoadString(g_hAppInstance, IDS_GRPCLASS, + szGrpClass, ARRAYSIZE(szGrpClass)); + + // Register the group window class + wce.cbSize = sizeof(WNDCLASSEX); + wce.style = CS_DBLCLKS; + wce.lpfnWndProc = GroupWndProc; + wce.cbClsExtra = 0; + wce.cbWndExtra = 0; + wce.hInstance = g_hAppInstance; + wce.hIcon = g_hGroupIcon = LoadImage(g_hAppInstance, + MAKEINTRESOURCE(IDI_PROGGRP), IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); + wce.hCursor = LoadCursor(NULL, IDC_ARROW); + wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wce.lpszMenuName = NULL; + wce.lpszClassName = szGrpClass; + + if (!RegisterClassEx(&wce)) + return FALSE; + + // Now we can create the groups + if(LoadConfig(FALSE, FALSE, TRUE) != RCE_SUCCESS) + return FALSE; + + // TODO: if loading groups fails, throw an error + + return TRUE; +} + +/* * * *\ + CreateGroup - + Create an MDI window from a group structure + RETURNS - + Handle to the new group window + or NULL on failure +\* * * */ +HWND CreateGroup(_In_ PGROUP pg) +{ + MDICREATESTRUCT mcs = { NULL }; + PGROUP pGroup = NULL; + HICON hIconLarge = NULL; + HICON hIconSmall = NULL; + HICON hIconTemp = NULL; + HWND hWndGroup = NULL; + HIMAGELIST hImageList = NULL; + HWND hWndListView = NULL; + RECT rcGroupWindow = { 0 }; + LVCOLUMN lvc = { 0 }; + + if (pg == NULL) + return NULL; + + // error checking, if we get trash don't try to + // make a group out of it + // TODO: if a group is garbled, throw an error + // and ask the user if they want to delete it! + if (pg->dwSignature != GRP_SIGNATURE) + return NULL; + + // allocate memory for a new group + pGroup = (PGROUP)malloc(CalculateGroupMemory(pg, 1, 0)); + if (pGroup == NULL) + return NULL; + + // clean up the memory if it's valid + ZeroMemory(pGroup, sizeof(*pGroup)); + + // copy over the group structure + *pGroup = *pg; + + // TODO: get group minimized/maximized flags + + mcs.szClass = szGrpClass; + mcs.szTitle = pg->szName; + mcs.hOwner = g_hAppInstance; + if ((pg->rcGroup.left == CW_USEDEFAULT) & (pg->rcGroup.right == CW_USEDEFAULT)) + { + mcs.x = mcs.y = mcs.cx = mcs.cy = CW_USEDEFAULT; + } + mcs.style = WS_VISIBLE | WS_THICKFRAME | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + // TODO: should I pass the pointer to the group through here + // or is it better and easier to just do it with GWLP_USERDATA? + mcs.lParam = (LPARAM)NULL; + + if ((hWndGroup = (HWND)SendMessage(hWndMDIClient, WM_MDICREATE, 0, + (LPARAM)(LPTSTR)&mcs)) == NULL) + return NULL; + + // Associate the group structure pointer to the group window + SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup); + + // Resize the group + if (pg->wp.length == sizeof(WINDOWPLACEMENT)) + SetWindowPlacement(hWndGroup, &pg->wp); + + // Load the group icon + if (ExtractIconEx(pg->szIconPath, pg->iIconIndex, &hIconLarge, &hIconSmall, 1)) + { + if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON, + ICON_SMALL, (LPARAM)hIconSmall)) + DestroyIcon(hIconTemp); + if (hIconTemp = (HICON)SendMessage(hWndGroup, WM_SETICON, + ICON_BIG, (LPARAM)hIconLarge)) + DestroyIcon(hIconTemp); + } + + // Get the group window rect + GetClientRect(hWndGroup, &rcGroupWindow); + + // Create the group window ListView control + if ((hWndListView = CreateWindowEx(WS_EX_LEFT, WC_LISTVIEW, + TEXT("ListView"), + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | + LVS_ICON | LVS_SINGLESEL | LVS_AUTOARRANGE, + mcs.x, mcs.y, mcs.cx, mcs.cy, + hWndGroup, NULL, g_hAppInstance, NULL)) == NULL) + return NULL; + + // ((LVS_AUTOARRANGE & bAutoArrange) * LVS_AUTOARRANGE) + + // Resize it to fit the window + SetWindowPos(hWndListView, NULL, + rcGroupWindow.left, rcGroupWindow.top, + rcGroupWindow.right - rcGroupWindow.left, + rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER); + + // Add the explorer style because it looks good + SetWindowTheme(hWndListView, TEXT("Explorer"), NULL); + + // Get this bad boy an image list + // TODO: if cxicon/cyicon change make sure we handle that + // don't require a program restart, DPI!!! + hImageList = ImageList_Create(GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), ILC_COLOR32, 0, 1); + ListView_SetImageList(hWndListView, hImageList, LVSIL_NORMAL); + + // since the list is viewing we can load items if applicable + if (pGroup->cItemArray > 0) + LoadItems(hWndGroup); + + // TODO: make sure the groups delete their icons upon destruction! + // AND IMAGE LIST!!!!!!!!? i think it's nuked w/ listview though + return hWndGroup; +} + +/* * * *\ + RemoveGroup - + Removes and cleans up a group window + RETURNS - + TRUE if cleanup is successful, + FALSE otherwise. +\* * * */ +BOOL RemoveGroup(_In_ HWND hWndGroup, _In_ BOOL bEliminate) +{ + PGROUP pGroup = NULL; + BOOL bReturn = TRUE; + + // TODO: do i have to delete the titlebar icons? + + if (bEliminate == TRUE) + { + // TODO: remove group from registry + // if successful blah blah blah + bEliminate = TRUE; + } + + // get the group struct pointer + if ((pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA)) == NULL) + bReturn = FALSE; + else + free(pGroup); + + // close the group window + SendMessage(hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndGroup, 0); + + return bReturn; +} + +/* * * *\ + CreateItem - + Creates a new program item + RETURNS - + Pointer to the item if successful + NULL otherwise +\* * * */ +PITEM CreateItem(_In_ HWND hWndGroup, _In_ PITEM pi) +{ + PGROUP pGroup = NULL; + PGROUP pNewGroup = NULL; + PITEM pItem = NULL; + HWND hWndListView = NULL; + HIMAGELIST hImageList = NULL; + HICON hIcon = NULL; + LVITEM lvi = { 0 }; + + // we actually just want the group pointer lol + pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA); + + // return NULL if we can't get to the group or item + if (hWndGroup == NULL) + return NULL; + if (pGroup == NULL) + return NULL; + if (pi == NULL) + return NULL; + + // get the listview window + hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL); + if (hWndListView == NULL) + return NULL; + + // if we reallocate memory then send the new pointer in + pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 1, 0)); + if (pNewGroup != NULL) + { + pGroup = pNewGroup; + SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup); + } + + // add the item + pItem = pGroup->pItemArray + pGroup->cItemArray; + *pItem = *pi; + + // increment the item counter + pGroup->cItemArray++; + + // then get the pointer to the group's image list + hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL); + + // extract that icon son!! + hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex); + + // populate the listview with the relevant information + lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + lvi.iItem = pGroup->cItemArray; + lvi.iSubItem = 0; + lvi.pszText = pItem->szName; + lvi.cchTextMax = ARRAYSIZE(pItem->szName); + lvi.iImage = ImageList_AddIcon(hImageList, hIcon); + lvi.lParam = (LPARAM)pItem; + + // copy that bad boy into the listview + ListView_InsertItem(hWndListView, &lvi); + + // get that hicon outta here + DestroyIcon(hIcon); + + // this is all terrible i'm gonna rewrite this whole file + // why is the listview even touched here just... omg... + // BAD!! bad functions + + // TODO: fail if the listview item isn't added + return pItem; +} + +/* * * *\ + LoadItems - + Loads all of the items in a group structure + RETURNS - + TRUE if successful + FALSE otherwise +\* * * */ +BOOL LoadItems(_In_ HWND hWndGroup) +{ + PGROUP pGroup = NULL; + PGROUP pNewGroup = NULL; + PITEM pItem = NULL; + HWND hWndListView = NULL; + HIMAGELIST hImageList = NULL; + LVITEM lvi = { 0 }; + UINT cItemIndex = 0; + HICON hIcon = NULL; + + // return NULL if we can't get to the group + if (hWndGroup == NULL) + return FALSE; + + // retrieve the group pointer + pGroup = (PGROUP)GetWindowLongPtr(hWndGroup, GWLP_USERDATA); + if (pGroup == NULL) + return FALSE; + + // get the listview window + hWndListView = FindWindowEx(hWndGroup, NULL, WC_LISTVIEW, NULL); + if (hWndListView == NULL) + return FALSE; + + // make sure we have enough memory for the items + pNewGroup = realloc(pGroup, CalculateGroupMemory(pGroup, 0, 1)); + if (pNewGroup != NULL) + { + pGroup = pNewGroup; + SetWindowLongPtr(hWndGroup, GWLP_USERDATA, (LONG_PTR)pGroup); + } + + // then get the pointer to the group's image list + hImageList = ListView_GetImageList(hWndListView, LVSIL_NORMAL); + + while (pGroup->cItemArray > cItemIndex) + { + pItem = pGroup->pItemArray + cItemIndex; + + // extract that icon son!! + hIcon = ExtractIcon(g_hAppInstance, (LPWSTR)pItem->szIconPath, pItem->iIconIndex); + + // populate the listview with the relevant information + lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + lvi.iItem = cItemIndex; + lvi.iSubItem = 0; + lvi.pszText = pItem->szName; + lvi.cchTextMax = ARRAYSIZE(pItem->szName); + lvi.iImage = ImageList_AddIcon(hImageList, hIcon); + lvi.lParam = (LPARAM)pItem; + + // copy that bad boy into the listview + ListView_InsertItem(hWndListView, &lvi); + + cItemIndex++; + } + + if (hIcon) + // get that hicon outta here + DestroyIcon(hIcon); + + // TODO: fail if the listview item isn't added + return TRUE; +} + +/* * * *\ + RemoveItem - + Removes a program item + RETURNS - + TRUE if item was successfully removed + FALSE otherwise +\* * * */ +BOOL RemoveItem(_In_ PITEM pi) +{ + // TODO: implement this + // return NULL if we can't get to the group + if (pi == NULL) + return FALSE; + + return FALSE; +} + +/* * * *\ + ExecuteItem - + Runs a program item + RETURNS - + TRUE if item was successfully ran + FALSE otherwise +\* * * */ +BOOL ExecuteItem(_In_ PITEM pi) +{ + // TODO: nCmdShow from program item flags + ShellExecute(g_hWndProgMgr, TEXT("open"), + pi->szExecPath, NULL, + (pi->szWorkPath != TEXT("")) ? pi->szWorkPath : NULL, + SW_NORMAL); + + // TODO: if item has run as admin as a flag, + // run it as an admin + + // TODO: make sure environment is + // refreshed before execution + return FALSE; +} + +/* * * *\ + UpdateGroup - + Updates group information to prepare + it for being saved. + ABSTRACT - + This function will update all of the + relevant structures in a group struct + in preparation for saving the group. + RETURNS - + Nothing. +\* * * */ +VOID UpdateGroup(_In_ PGROUP pg) +{ + DWORD dwFlags = 0; + HWND hWndGroup = NULL; + + // Set the important flags + pg->dwSignature = GRP_SIGNATURE; + pg->wVersion = GRP_VERSION; + + // Set the group checksum + pg->wChecksum = 1; // NOTE: implement this for real later lol + + // TODO: set name and group flags + // pg->dwFlags = GRP_FLAG_MAXIMIZED;// GetGroupFlags(pgw); + + // Set FILETIME + GetSystemTimeAsFileTime(&pg->ftLastWrite); + + if (hWndGroup = GetHwndFromPGroup(pg)) + { + // Get the group window rect and name + pg->wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hWndGroup, &pg->wp); + GetWindowText(hWndGroup, pg->szName, ARRAYSIZE(pg->szName)); + } + + return; +} + +/* * * *\ + GetHwndFromPGroup - + In goes a PGROUP out comes a HWND + RETURNS - + HWND. +\* * * */ +HWND GetHwndFromPGroup(_In_ PGROUP pg) +{ + EnumChildWindows(g_hWndProgMgr, (WNDENUMPROC)GetHwndFromPGroupEnum, (LPARAM)pg); + + return hWndFoundGroup; +} + +/* * * *\ + GetHwndFromPGroupEnum - + Enum Function + RETURNS - + HWND. +\* * * */ +BOOL GetHwndFromPGroupEnum(_In_ HWND hwnd, _In_ LPARAM lParam) +{ + if (lParam == GetWindowLongPtr(hwnd, GWLP_USERDATA)) + { + hWndFoundGroup = hwnd; + return FALSE; + } + else + { + hWndFoundGroup = NULL; + return TRUE; + } +} + +/* * * *\ + VerifyGroup - + Verifies that a group contains the + correct information about itself. + ABSTRACT - + This function will check the checksum, + verify the number of items, check other + parts of the strucutre. If requested, + it will repair the group if it is damaged. + RETURNS - + TRUE if group appears to be fine + FALSE if the group is damaged +\* * * */ +BOOL VerifyGroup(_In_ PGROUP pg, _In_ BOOL bRepair) +{ + if (pg->dwSignature != GRP_SIGNATURE) + return FALSE; + + // if (pg->wVersion != GRP_VERSION) + // some sort of version difference handling + + if (pg->wChecksum == 1234) + // TODO: calculate checksum function + return FALSE; + + // TODO: use ftlastwrite to throw an error + // if system clock is in the future + + // calculate the size of the group based on item of numbers + + // TODO: change to return a dword error value + return TRUE; +} + +/* * * *\ + CalculateGroupMemory - + Calculates the memory needed by a group. + Takes a group structure pointer and the + number of desired items as input. + RETURNS - + Size in bytes that a group should take up. +\* * * */ +UINT CalculateGroupMemory(_In_ PGROUP pGroup, _In_ UINT cItems, _In_ BOOL bLean) +{ + UINT cbGroupSize = 0; + UINT cItemBlock = 0; + + // first add the size of a group strucutre + cbGroupSize += sizeof(GROUP); + + // calculate the total amount of items wanted + cItemBlock = pGroup->cItemArray + cItems; + + if (!bLean) + // round the amount of items to the nearest but highest ITEM_BATCH_COUNT + cItemBlock = ((cItemBlock + ITEM_BATCH_COUNT) / ITEM_BATCH_COUNT) * ITEM_BATCH_COUNT; + + // finally calculate the total group size + cbGroupSize += cItemBlock * sizeof(ITEM); + + return cbGroupSize; +} + +/* * * *\ + GroupWndProc - + Group window procedure. + RETURNS - + Zero if nothing, otherwise returns the good stuff. +\* * * */ +LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch (message) + { + + case WM_CREATE: + { + CREATESTRUCT* pCreateStruct; + MDICREATESTRUCT* pMDICreateStruct; + + // code borrowed from winprog + pCreateStruct = (CREATESTRUCT*)lParam; + pMDICreateStruct = (MDICREATESTRUCT*)pCreateStruct->lpCreateParams; + + return 0; + } + + 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; + } + + } + return 0; + } + + case WM_SIZE: + { + HWND hWndListView = NULL; + RECT rcGroupWindow = { 0 }; + + // get the group window rect + GetClientRect(hWnd, &rcGroupWindow); + + // find the listview control + hWndListView = FindWindowEx(hWnd, NULL, WC_LISTVIEW, NULL); + if (hWndListView == NULL) + break; + + // resize it to fit the window + SetWindowPos(hWndListView, NULL, + rcGroupWindow.left, rcGroupWindow.top, + rcGroupWindow.right - rcGroupWindow.left, + rcGroupWindow.bottom - rcGroupWindow.top, SWP_NOZORDER); + + return DefMDIChildProc(hWnd, message, wParam, lParam); + } + + default: + return DefMDIChildProc(hWnd, message, wParam, lParam); + } + + return TRUE; +} diff --git a/PROGMGR2/group.h b/PROGMGR2/group.h new file mode 100644 index 0000000..0232720 --- /dev/null +++ b/PROGMGR2/group.h @@ -0,0 +1,92 @@ +/* * * * * * * *\ + GROUP.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program group/item structures, functions and definitons + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#pragma once + +/* Definitions */ +#define MAX_GROUPS 512 +#define MAX_ITEMS 512 +#define MAX_TITLE_LENGTH 255 // Same as the registry key name max length +#define ITEM_BATCH_COUNT 8 +// Group Format Definitions +#define GRP_SIGNATURE 0x47324D50L // PM2G +#define GRP_VERSION 2 // Increment for breaking changes, format version +// Group Flag Values (DWORD) +#define GRP_FLAG_COMMON 0x00000001 +#define GRP_FLAG_READONLY 0x00000002 +#define GRP_FLAG_MINIMIZED 0x00000004 +#define GRP_FLAG_MAXIMIZED 0x00000008 +// Item Flag Values (DWORD) +#define ITM_FLAG_HOTKEY 0x00000001 +#define ITM_FLAG_PRIVILEGE 0x00000002 +#define ITM_FLAG_MINIMIZED 0x00000004 +#define ITM_FLAG_MAXIMIZED 0x00000008 + +/* Structures */ +// Item Structure +typedef struct _ITEM { + // Item executable and name + WCHAR szName[MAX_TITLE_LENGTH + 1]; + WCHAR szExecPath[MAX_PATH + 1]; // Path of the executable + WCHAR szWorkPath[MAX_PATH + 1]; // Working directory + // Item flags + DWORD dwFlags; // Use with ITM_FLAG_* values. + UINT uiHotkeyModifiers; + UINT uiHotkeyVirtualKey; + // Icon + WCHAR szIconPath[MAX_PATH + 1]; + INT iIconIndex; +} ITEM, * PITEM; + +// Group format, .GRP +typedef struct _GROUP { + // Group file header + DWORD dwSignature; // Set to GRP_SIGNATURE + WORD wVersion; // Group format version + WORD wChecksum; + // Group information + WCHAR szName[MAX_TITLE_LENGTH + 1]; + DWORD dwFlags; // Use with GRP_FLAG_* values. + FILETIME ftLastWrite; + // Window information + RECT rcGroup; + WINDOWPLACEMENT wp; + // Icon + WCHAR szIconPath[MAX_PATH + 1]; + INT iIconIndex; + // Items + WORD cItemArray; // Number of items in pItemArray + ITEM pItemArray[1]; // Array of items +} GROUP, * PGROUP; + +/* Global Variables */ +extern HWND hWndMDIClient; + +/* Local Variables */ + +/* Function Prototypes */ +BOOL InitializeGroups(VOID); +// Group Management +HWND CreateGroup(_In_ PGROUP pg); +BOOL RemoveGroup(_In_ HWND hWndGroup, _In_ BOOL bEliminate); +// Item Management +PITEM CreateItem(_In_ HWND hWndGroup, _In_ PITEM pi); +BOOL LoadItems(_In_ HWND hWndGroup); +BOOL RemoveItem(_In_ PITEM pi); +BOOL ExecuteItem(_In_ PITEM pi); +// Save/Load helper functions +VOID UpdateGroup(_In_ PGROUP pg); +BOOL VerifyGroup(_In_ PGROUP pg, _In_ BOOL bRepair); +// Helper functions +UINT CalculateGroupMemory(_In_ PGROUP pGroup, _In_ UINT cItems, _In_ BOOL bLean); +HWND GetHwndFromPGroup(_In_ PGROUP pg); +BOOL GetHwndFromPGroupEnum(_In_ HWND hwnd, _In_ LPARAM lParam); +// Group Window +LRESULT CALLBACK GroupWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); diff --git a/PROGMGR2/grpupdat.h b/PROGMGR2/grpupdat.h new file mode 100644 index 0000000..e4fb1e2 --- /dev/null +++ b/PROGMGR2/grpupdat.h @@ -0,0 +1,38 @@ +/* * * * * * * *\ + GRPUPDAT.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Header containing classic program group structures + in order to facilitate conversion to the new format. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#pragma once + +/* Includes */ +#include + +/* Definitions */ +// Group signatures +#define OLDGRP_SIGNATURE 0x43554D50L // PMUC + +/* Structures */ +// Old group format, .GRP +typedef struct _OLDGROUP { + DWORD dwMagic; // Set to OLDGRP_SIGNATURE + WORD wCheckSum; // Seemingly unused + WORD cbGroup; // Size of group + RECT rcNormal; // Window rect + POINT ptMin; // Minimized window position + WORD nCmdShow; // Min/max state + WORD pName; // Group name + WORD cxIcon; // Icon width + WORD cyIcon; // Icon height + WORD wIconFormat; + WORD wReserved; // Unused + + WORD cItems; // Number of items + WORD rgiItems[1]; // Array of item offsets +} OLDGROUP, * POLDGROUP; diff --git a/PROGMGR2/icons/common.ico b/PROGMGR2/icons/common.ico new file mode 100644 index 0000000000000000000000000000000000000000..530e4e96975aa6e0c6e73c560199512b9bbdab1a GIT binary patch literal 1078 zcmcIjy;8$43|7le&2fkG2${G(Mu*(Nz}mS?%--TH9`hD`1s)*}(7V0{8(vD75TE2Y z=|LGdj<1!aFS2CCQix_Wr?M=d&*^1ObW21N;u8bk6utBK3mHkzuc?vC?+IS(ZO z$UoF$<=x+>dbEDwsGL!--i>h62JR^`*R>O_@lWvgJ1acO`InC)X9Ab_zE*#_n6zTQ zlr_P5l%23bV$_#ubst)T_xX{l<6FMmuR#xOkkqGfGyCN=q=e)-?_g($ zPb48=s9|BQRbhqst2sxsBHxcsg*eY>akS2((c6z#)o_V^v;AKDZ2JaU;e1M<{fRN= QKIMLl-%UR6FZV35pE^o#7ytkO literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/bkgsrc.pdn b/PROGMGR2/icons/misc/bkgsrc.pdn new file mode 100644 index 0000000000000000000000000000000000000000..8007263f87353f78b14ef0dd3c9f27b0384b67c8 GIT binary patch literal 16946 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 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/bkgsrctxt.pdn b/PROGMGR2/icons/misc/bkgsrctxt.pdn new file mode 100644 index 0000000000000000000000000000000000000000..ee3de6e54891132fef0b1fe655e25823de8598f8 GIT binary patch literal 32165 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 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/comms.ico b/PROGMGR2/icons/misc/comms.ico new file mode 100644 index 0000000000000000000000000000000000000000..5ff14f39e2dc74b044fcae1b254af830cb8012a4 GIT binary patch literal 1078 zcmcIjv1-FW3{{ds428y@;HhK`+!DAU89MZHZnL)@cro~A3>g~m5Pwd`122UP?vrJ? zHGw)yUMx#b(%I*G3ekd=lq50y6MZd-UWq7M%`FDs%gatZ7R<35H*uOddkCh#aC z@?IS72w|R@ra__WFX}puVEA#0Z!<`za9J^d%Rcaw5#M+6!0!fz{t%^-5FVn^NJ4m2 zUUEqYx0mbLm~^A-57&L28~&c5p6BIxXLicl^L}4@TPg2sUb?D2jXXS8t95-CxveV8 zW!<0sT-PU*mA9xeRo=Cxrz7VYL-r%_z$eF7xa>`FWF`LacV9&QAKtIK(PJuC>SpBa zkA1G^5p_Kio^zh#1g3M|AXYqT&WCeynQX*m0pk=lE^9F+EA}TM3*XrqqX6F;i2U0x Z59sv?A*fEOhf^K&JMQ?aY3q&WwLgzkk{|#8 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/console.ico b/PROGMGR2/icons/misc/console.ico new file mode 100644 index 0000000000000000000000000000000000000000..c3dff5bce3d9d6a910d8734011694133e2543361 GIT binary patch literal 1078 zcmd5)IS#@w5FCzz3g-!_5YM2X;5qI{=`zpCb13}-GqW2@u@E4IhJn4;PO>||23z!f zN4v*k3!DISoyX@5aNGfB=6cG7qCO$9x1ysXaU>S$rR0X1E+t`_CKihQQHneYe@aPx z!M#Ns#s+a{&L93E4g~=r=t6h{ES7s)!5@0XXDso$9XCZlkv@X;>Wl% z<5vppRw}4ct4h4IqN-S_RsR(61EE%E3kuQ-2}F?!R3JdGRY3)cs)emkTbdHinQ z*|OyazxG;lX70InzH{z5pU;^bKNlE1L`^kH^>j^?3ENgmMmgpV_}y%oD011bo~vS) zXnM>IYF%uR(xPIN7eJ$^^_V;83Hbb;NHiGn1cJVx-+gLIYU+ksJ2hpLo3#zLQI}(G zWg(u;w|%EmvdY1jD-_Ggq6|+7oN{u4%fKz3Y^1f6sacvUTV7HHVKLA9Q|)9;6u82&yu@eylZln^eIfsn3hKse zx)bLo%Fx`l#1Kp1Q`#Ukow8BX&=7sRA9@x^Jgevi9>wMQNTI94R!{E) zuhG4ELakPbWB|2wPm0uurbr%edO@r<3BYNe^{=k>wiXOcsmtSRO_x-ys%-R!!{>qD zwWF{RiHIR76rP9%g2Xo&T^s*@g0HQv;o&J}2n5@^7>E_c*g@D)ef5~(9!EpeAT^_$ zrion)qSp)1?u#=d#WsuDJUziOVXT%cr-3yc#4&hWCK(JRtq`mvr7w^Yrs zo>A&}i#L^OiCNE+mVy-tUV`+xT)5Q(podRV)IT4lC?_7#BsQ)L{qed;xb1ED6JH-k zMam3SNY~!NzbZ{T7*HI!lXR3#k0HvwRo|Lp7*zZes#v82z0DVLvsEZY?uoFQHM$LA z_BazD=9W^^jg7j{+^8-1(!9{jbc0=vv&ts@4~Q$q)-f_*C5TpzfXaJd#UBN5(+c!Y z%Sgb@_Ka{cXVzi*@;=}V1Arj}90gUR4{#EIOu)%~KsZMaa2e}7mqcL!U)l%0aR4}s zz{jox2FE@u@F@OQ@vp?(gyJ}eBZo#l3b%nikx(_#Ul<2J7Oq_(%|3w^ZtgGUamA>K z4YQ=1t)ii+4Wbze(Vcoz+Y}`-YA%i)^pL}r!fYWU*0a?}dOHsw%)(>4`vdHa_1Vt7 zZx-2itpAOIvE({8AmOEK!}iI37mLtQSB%j=ZAq4djy<# zMA74-RFUCJtzL4f4N+2zE@Orwqm~GbozQl@d=t?0py!(DaL`C#ljUxlA(N3tZ0|Y)cjgWdG_o2q?zj_# zeIneM2=7~_e*>1$I;>E3q~eF9FYZT2?8v7NA|Php1?-oNayZD8MLlPJ`M64ClV}<# z!7@YBNKpz)GY;Cxnl}_Mu9MFT8Z(H|r!ip|(u05;wz>oADC&`ukGia<;Wy6G!)JW1 zWbAzE&CRcIqjyyP{Bm*lT-0{%nDf>j>>N3IcD(lX=kI!|@!aQ1_v9bn{ljBVu3z4H z@lW5&K2iJE_ST7KUfp?mPyWiQ_wI(@IzIMg?+=5arFVXL;<49vo_G9pH~sFXfAP2P z&+oqe;7`|ox3m2F2fx1O{n6sH-|D{f@CC~^EKSzv^f~oadYHQ1WxM};_Dy;1p@&?~ z#V3CD?V;13dBrvT%#&Yu=E&3`5cknJPcQQ!dZQkfG1fW{n#2EI%is#%?YkmbGQ~nzk3j6iEr9bRq)m zut(o_^atGczzIOtS$^IDuP?xvb3N@s6HmzGIywe2L*^o*oXv4$NXr<^#GkWLEN}UndI4XA@AuCY>-vhn zuE%2a_PqYD?ziTz>NW3|w(oa!T(mJJPp@zJcFaHImAI+b95)Qj>o0HSF*Wd51WtaU z*SUgpE**_c%{Flx@-zg@xk3x)zWeNHcLZIhJ%--jnX9a41 Vs2A^(_ak~AjIRHhM}PO)`vG#=Fk=7! literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/document.ico b/PROGMGR2/icons/misc/document.ico new file mode 100644 index 0000000000000000000000000000000000000000..c4e9c3dd12bcd9e470e1d691a5d7b66ef60d8066 GIT binary patch literal 1078 zcmcIiyAgvh3>73rs^Ae^|;uBSZYYv>&S3I n{Atg}J{g+|0rx!SUEP2BQ-U}j@4d`P=3!(Gs5auCF7w?tP2!H` literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/msdos.ico b/PROGMGR2/icons/misc/msdos.ico new file mode 100644 index 0000000000000000000000000000000000000000..6a8d6e57d0273d80b1d6f31a3acbdbfc5df7b36e GIT binary patch literal 1086 zcmdr~u};G<5WPf|vP23JACOKJBb|c8P$oVBK7knlLQD?-ft1f+qB2WaBKZrDpdHFY zP$Nj)+IgI589-4628Nz>=X>vbXWz+09{JSm`n-Fz>k;*c7;iD^(2GxW#N3YKSPxj; zxi$gN7XFtQzo9{%U<6_tp|Go|p$}(2xLVX0H^o{b#7eh$5*)mE2?Y zFvUV?%nJk4koa?6oz|XH7iE*KopcSPl+2~{HBC0Fv4Zgm@U<>;vm~TYDjDXKOI}1_ z9acxSrsmP8;MC{$2@h literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/pmcomm.pdn b/PROGMGR2/icons/misc/pmcomm.pdn new file mode 100644 index 0000000000000000000000000000000000000000..a755cd0d0fb9742026d92bca3e3c2abbe4a476ad GIT binary patch literal 4165 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 Izl82T0KnP*UH||9 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/pmsheet.pdn b/PROGMGR2/icons/misc/pmsheet.pdn new file mode 100644 index 0000000000000000000000000000000000000000..536c8541ff75ac02b54fa3f61fc8c0fbacf1e1ef GIT binary patch literal 3935 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 Xwg2Y3;`f>Yvg=x~@Tu96FdF_hD*3VY literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/spsheet.ico b/PROGMGR2/icons/misc/spsheet.ico new file mode 100644 index 0000000000000000000000000000000000000000..1f3b9190304856be7f7624995082cb395d9f5e05 GIT binary patch literal 1078 zcmd^7F%H5o40H1ke7P}qI1!)1y$z(zT#IppZmlvX_Z}4@%wQ)V4BZ3jyflu2kRX4 KKfdX*eER@k%6x+W literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/superman.ico b/PROGMGR2/icons/misc/superman.ico new file mode 100644 index 0000000000000000000000000000000000000000..8b324239acf4cc6f3cf858a0b3e64d0d9f2bd19a GIT binary patch literal 766 zcmZvZu};G<5QcvvqzDNq&4Sd4jJyRIGV(Cl!WM7whIpe49s3ZKSQyQgq3ZG9*-2Bx zrN5o;{`1*!0mrAVchLC01D-g)P&L(14)+`ZPw)TmH0gMsCXRfiJf>-)A@+lazEONM zrObFd9NHy}-xg|H<@m>s$F-nQUvOL+JQy>PI^Z*LN;KH-GwU(nsw(>^i#`PJs^rJu z(Z9>=U1pgB`VX1A#HBD%+^__%Tv>nmEEqOClLL8Ye#9UW7@by%*hm}`MoSX6HtRcV z%E@+vtj+b~!ctClz$vFX;(&_AK zjhA)?tF5hV!(`Lc72>ld&RTJ%XvhzB%2IEu6CAnV+JdDjekV1Vp82kNW!`iF29>rx JbLpl0l3&(El79dI literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/wfdir.pdn b/PROGMGR2/icons/misc/wfdir.pdn new file mode 100644 index 0000000000000000000000000000000000000000..c544c4945908643e26873c05f7d7450869156a12 GIT binary patch literal 3971 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 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/wftree.pdn b/PROGMGR2/icons/misc/wftree.pdn new file mode 100644 index 0000000000000000000000000000000000000000..909036b7824e7f8050b9b27dabacf348c6d13a4a GIT binary patch literal 4054 zcmd^BYi!%r6((&-7G3ADHeHsaO*O?U2H4Zvl8ssEsHY`ck|kNPogmXF>WZQzkqjS_ zm8M<(^Z^uTF>I|7bPX^JNH?_I5MV`y7DIxi7_tUMu>yM*$bfCgpCV|`VsqRr_3k0% zSkBU=`>|iS1P^)7z4tr!p7Ze>&PLMSulEs?QbkBK84lUnd_}DV?Ou=FRzo~jQ;qiq z(?PNlv}3ixv`}T9S8GMA;YA^6_c^?-amTo8-0Sd+`Q7$|ldPtwV)NjnTGN_kn()mIyTHx?o7`ikUrc?M4ib@GNu4@+3`J5|3%ZiWnXF-z_vITbt zFIZk`x5gK<1yB|X(d9yJF-&u*2;Bw^ZrrR>Z+a(QJW9KDfT>C>nJE}UPG_5D^6j*4 zE4&a&%rAibKm?0SyFE2k_SfpLUUoI2*<#i=7x2s#vVmxV=3?#QLaREGi%s$TjJp+3 z)o4R*X6bz1>56sKC2trH9ZfC?ouufb^HMWjkBf(j%LQdBSy1A5FLJsbm)YrbmFA)` zfvuq=orwGMp7xx4Y$;r0=Ti$4nYb@88}mfnq0IcT`b;su$kk$tY-}NLD1>s=c^XHD z4%8On**Ui`7K+h_YOPL4C`4OmOyiIFlEvn<%NZ_b3S1<%C~N+(Sjm;=+u6{ekxYh5 z)yKw803`*uSlYTDi(vQW}V3vgT&NL(tbfxkeos) zQ^8wGsHmwBCW7eiC-3ito&mbg@QMm2v0At1I|`oa=pNt-+3knLMgy@b{swKz$Uyt`4u>eT{7pMU&pf`wb6BxZEO!_`bDP~EOEu|DMz$2vbjS5xDp%xFh z3opXqwOV1S4}*U9A%Y+=-T)j?=QWJ<|Lv{_xam6nhVPD}0&V*1sAF!yr%I9*3M;k^ zqh-G8P#Mm3*mcALw2DlE%Eni46?Bc+Z4I1^>~6o^rgkKxS3?~jXlLUwsVro*ajh8*7Gp= z(FWpj5sq$7@RAmWpB5f`Dv(NPcv@`oG9_ijZV2ju&1MaEnEyvRG@ zbA_*o+6Cf%EVlIxeGxylREn@Dqu$)O<V}O|CL5+NlqYY*vwb4251qhKzTklyqlqLg=Z-^tI2hH_~H!_NH0j-+jF+^2Rp6 z9i-Lz<=!E~xGuK>=$UXgUO{~ci_ILp2SC8Tx}*2v7iu3Cn-da|6|<+6gz3d;yCJZQo> zdP_u8s42>wP(x(v;4`>w-TMT7Qv0zmgCp+jN??RZV4CPZe+>qpO5hU@@k)qc>zpiV zLS;ad7?xK%l)t2ulRAI}39N>QTZXYPyZy^<|AuAq zPuMb8$0LLpsQ5YQ3-e(kX5iCj5fGwp#q8(Qn%_s&7-d%f_pw$`70EKH;9-g+fuaPY zW@zMqO@DyE?JoJjAR&U_eG&o&F5Ps#GTwK}HS^wQ9myTaPyYkbI zpIe%%U6*6t>mLoZ9=rDDcaEPVn8y}uS;+T#rT?9<;@{~=v?`|KM>pDMk1 z_Ellw%BpnXm#Y#xT>9&iyVrlbZ~yUT=D_ujKRvmcdH2jKKU!N^yRoviZeBaNcjV%w zXL;iQkiU%fM916b1%I3`kAl(!N2bn_pZz5FTDEw?-`{@jCu`4NeQ^GhKc0T{=SyeSuk3&Q tJ?D*Yo_yz5Z?BzAe{kxZ*prW3TYc)rdk3IY6DLYX`yStM`9;{#zX6ub=f3~| literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/misc/winoldap.ico b/PROGMGR2/icons/misc/winoldap.ico new file mode 100644 index 0000000000000000000000000000000000000000..53bc6bfcc92f5d8804e5612d83509e41fa733701 GIT binary patch literal 1078 zcmcIiF>b>!3}n&{oeDp}Q;}z6;E;`9(H4&y{VYGHqX+HkooFFaQq)0%zUL}VD8pAI7LFCr)GjgT{henfKJ zj;poyl#J%;pY6fFi$~XjC*I$sZ*KB+W+fVaiSt|hftL#(>d}|$8g|Od9@uY!y&%7^ z^In2|&ORO?wa*vm75~-eTb^ou!-RsP=vV=@ZQZ!3+cn?(JwV~>y59D^zM4qleoUylS zhm@2Do^q`@Gxyv(-#Pc3&*w}wn)ZESgqmrIa-zvs39}}NdM)hmc^yoRNY$F&dv5R@ zqH19Ws5O3-h!045tpplLk;4wZ)93a&10jFF>GQk&UdQZ=(AIRNIXk1*+RX~nlB;2d zRElKsYwm;bs=~rZ7mBr5u?kNdPT4BQrr;KdwGwLF&>Tt^^6mtyYJOolhnl>cD|#aE z!urbEYOtIuqOwqotrzoUj;*Gm>>6rdRI@IZ3nz)yh2@&DFD}j{GeuD2VCOTg)_f4R zCWTn-K>_wgHMAdyvVypJG>!(jMxmIGl%ln)`e0^0suZhSjLQeJA=kumBC~KPt%s(n z(}A4ipIgpFQ<-dlD{?A3uN(@_x5P-1^~r@qu29XmOFYL#Hqt3R;a=%f(g{UO)nnN> zfv88=b<(Mn)s$yF*Qz#}{zSc)tLn>a(4#0?EP6EFIhs;p!bUzD4J4D5T)dR6dqus> z@%3b9P09jTWg$|CYucw4UtFuv=h^5_m|CFm9+K8-A zxI$B|i9$W;;XDi8Lq>cckflui;1pL*B*G5HH9O39^I?WRIUgRRc~3C_^{Ij1xlM9_iqnlnyhqDq1joG$T=HUT*GGv39; z{?>x7N^*6QX=;L^Hl)g6INVP7T|WwyK!BeTrlvh1pP#scp~I8^Pw>Nwhw<=~eG~-K zzw8hz%5DZ>M)kF0hI=e6UWL@`VO5pyU?3-!BnsUg~z@?=%QN(C=LdTln`>IBfS{Sn?1KXD!T&1$mF%~nxE;jqk?{|~ZKzLh zib@6xFCixWFNWUQw! zTF7|sxz|YgJ9i+A!ect{KK3RCY-isyi|o5~@Qp&x4U7kEv)wbe)H80#VE_cN-+|)8 zAa*MBM_@u@fQ?A+g9rPaAa*v~1rsyA_`f-gCD&Skgo~M$>EnYg7NMg?dJEb_T2Y&P zqd!F-4L?7MHqp;(9UFNu)U7QVG)s|~HG!AiuxNq`J(STDX)0MhK5*cBV`6l_#4+AUq2srV$q(yk4UR9O0ELxQoFGzaFZiFJGh=j&YXu46p z321s`-(d0$W*X_nSZpWU0)3P+`@HKuubqKMn(CTQL2dajuNwR^>eA8@WkVnwG!ocg zxdUg&WTX+(zaE3T{bL|#WHn~oaxVz8XL{W;y=|HPJy=HTutJ%UiXV`^xE~!cBcI-n zfS7$7u)nI;rv3IBuVsxdADc*)iK-G2mhCi+6s52<)Zps-1TF|_Rr1B{%+&gPwp4L6g%_6O;0{Fdi)2E{FZv# z;y99f!<%ze*57Ii+}&ar^b$4`c?OZcOU-jcb<7JKC=j(j+??8PdcXKcMzp;O% z!V&AU?@-n!zMP+oK6Bu$H+}zTz4+QMGH1)&*3VpDI9vYXW$l$yuV1-y?c{4e{MLc< r7hipvI5-n;{vz?kY$mtCct6}thkqRJaU-bIfyAa$*_=t z?Du=_3DoqQbXe#>G;WxdnD1cUhk z>H(*4WkH_oJVoD#_hj~)je7r1?#kf*K(05Av2;RJ@`-Qi&Cm(LPp1YU!u#~Vmm9&@L(v%dIX0umMbp!nDeku{{ty2*5~%}oa1l$ zoEH&8o}`L_Nafj7Y$8g1`+B8hh1ryq_n)qR3EcI~(SFFU)ysSKVXRxK$5@AWTl)7B J`<=Ak^cw^jWxD_X literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/pmgroup.ico b/PROGMGR2/icons/pmgroup.ico new file mode 100644 index 0000000000000000000000000000000000000000..1ceac12ca5343d227392fc1c262c98b2337f9f7a GIT binary patch literal 1078 zcmcIiJ8r`;3}w;}QWUU!1W!edks(7bklCF&YqPd!^euXY9>E7F+G})5xw!6B_EC!L z8Z{iCMPEXR6iMlsB+-JFR1`V(b9!A8-4IcpM|-^>%Fc+^I4d9AViR&GDiIz| zXx_&SD^!T5rfJ}i@Fx+~Ao%H#E+3fb$i^><72|s2bsv|TT}j>?39-vNYvk6 z7?Ep8b}%8nEQR?I_EWT5*m7kgdycjs*04$WJsBud@15dfwJ_k4_^xU%9kEDNS-mgh z-^1TUKCJIw-u1TNQ$v1N9r+E6kUuJ4ZQV9ugNx~#ee3I$pRq&UkNd{$s_-%MP;T=P z|Km+H(K**SE+A>n8|Vq@Q;F~xYG|12uwjMzt2sZ`$+}3yy0&Ct1G|)m&$r>6&AaJd etiynrZaEvXPNzG0Z yf?AOe;;NF&xy-Sp>6}M$#joc4sgv{hL*CzWfwey=CGC^;!)YJ%KfX~}o_zp__Qsz8 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/progmgr.ico b/PROGMGR2/icons/progmgr.ico new file mode 100644 index 0000000000000000000000000000000000000000..1cb5e7c18837583edbe68af2aaf5c4979ba7da0e GIT binary patch literal 5414 zcmdT|zi(Vc5MC3+or1*P35k^FGUXwc6kHL}I*m(|R2CI^o!g~)FV!U_;(q`|`~xm1 zPoYW~NQEef^iZ&kBRj)4GdsKc-n}!15Cd!N?aq8VKX!I^cAuTwa&NoEVj}Hl*PZ*s zIX9n2`W@%K25);?>7UJrvp@}~tnZ@2V|ZYQoe+t`!$a_b zBgXMVu|ts{WiYz2G{YsBKz%S+GM;)K=B%6~Zrx0|K;4CS+qM_tP_YTO32eZZ=2O`g z{v{kPrZR*Vk*EgoY@mZDrRWeAt98DEmwI^-+op#XdZ}%R?)Pzow&lh5m9!!sqY~<6 zeYEFk|1KSUdZ&u2U_Y)ZxQ;v#{0O1lCprhNrH4l@k=pmv z#i7vj%KQZ9s1T|CQhrYDGnR*cu%`H}UHWyJ=BM$4jNxaiUE28&LuQ444Q65TkH4oE z-x7T_tKzJopY1!R`d7erh`yXvyj3T{mysC9@kvGSnfH(rp5jp{d(84Elas*l=Q!5O zFO(;GZB$tKnFcmM!|ZB zukoz~)W`KwN-~3ZA>PGtFl2sNyoVP+>~`$0!yWnlstFyE&{|aU(#e=LJTKkf!}HRq z{Ga$|i`8v|$m)+h1g@$rO#jcj@}$BX{@HdbF2tK}`JFjOy^H#9yfeFdvI%fQN-q*4VzOH}f6mgf5~>(?g^zet*<|1^5%^gL{4NHXZMK+Iu2?#v=-Tdqnj4Jvx7m$6EQ0qT58r_lTZCRfk^~7Ju;C z;&(&WPw0>QVmQWOY~=rTi)cDyKUqKK7Wu31@Vc4NbSi%4@n^pfee^M%KB9JRabUY= zE216nABrBCSH=9kUC_+$=B9yrUz4Rs^Z0Z_X_8F(dwjd!^LR~)cCYvC3OY&aW7|&G zEAag4xChFabok{=%JI=NOZrJqmn&njVWi|+Y%a^U*vR+|b~|xlBJgM~uY0?x zmjC9jt>SC7*eD|Z23o#nwowu4a10 zUz?{7Bc69T=kk~z^*o8Z90@%~8CN>vdTsY13|apUx-0ug^@Og*6mTcblpV_$xnr9tJ9B&B4n1oaeTU zdKLRzq5)g-UkGkr&K92A({CQ{jt(l}<06qLjhj}!Z3}wrTfVv5v3EQqfaW2Sv5T|_ ZIyaUDKpSZ{gAuFf4wV3Ar;b3!`UgYo*6{!U literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/progmgrd.ico b/PROGMGR2/icons/progmgrd.ico new file mode 100644 index 0000000000000000000000000000000000000000..77cd3243eeaee6a26f2d709763e308bfb176c406 GIT binary patch literal 5414 zcmdT|y>1*g5T*jdcL)Nkf&giw(xo1O#UgHu>?@>9xt&@T0(QH5lRSe8l?VA1Qn*MV zAX^-u6bCckH$yIGf9~wWvEtC;lAMq8!y!4GvvU{jh4cPW+F!nQ?nmd`^>rG*bnaKs zuC8?a`&Z6=|E+VEmpXoR;oST0oO=Zxj~Y-Z?_A*=P7J9N(%|my4z%DRaeQLx#59OX zAbPU&>m_7{?q;!%)HB@3jl&S*n>h~G4&3~zl~(wZS34e-Fs6ug5Af|HIpOe8l>iHmy48 zcTVN+f$wA7H!Y8m`DGNMewGofD29WazO;Ah^IjR(~sTmmO@b|H}8t&zZJBu zDK~3c5~_TqC-^8RtmDO#3%ppUy}A6X8Lg+n zGr0PRlZ^d_e}YF`3tXtq;L=U=Wm&3UZehu`d{Rk_C%r|V1|@gBnpX)2>sJ< zOo0$C;Bt+x#DpGSRPh`9rMRthzKX~xWQ*+l5~cYbaxP1^(-empN#9%gsri~(F|+cp zC#@%RJEm03tnS6mbVWfQ4oJ}&W*oy{^QZ_r4-L``h?>xiVzCF=7W0OwosggCW;*6! zZlW_qLZ$>e4>j$~bfiYikdS%RpqKfQ5+U<>hvYB&fqEqs0-YI^&4cE8Ft~aF@Uisl8<~GX@5C=01kPsp)Yna=e3{?8i=Wiupa}nG zX!*`up?cKkd}qvQ2vF_JZPGF0H2+eJllY8ZyT?b3d58vHe%C;5O?KQsl-Z*5pVIwSR25Dc>2h<;P_5rFUNcS+C0J@!OJOUY))~|b190;mC$=s za2*T3;CgQaH}ZH_Xa0dtBu?Ry=DUgbG4RrsG0sT7#4?|F5}Wz6SdNWGhoY>W-N28I zv-DHra`Wf%vMPF;@+1{w$Xly2;qQESA66=(=4$0RzeK%4eU5W3-heLoUkJAE8(*~NrmZRI#6V9Y6gtN$4hw!-M#mV7nZGp+TZZJ;uFZ&!s-v9sr literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/common.pdn b/PROGMGR2/icons/src/common.pdn new file mode 100644 index 0000000000000000000000000000000000000000..39ceef9de468ac2cf374d2f98eb0fbc757ef7957 GIT binary patch literal 4249 zcmd^BYj7J^72dTiS&E$|OKq=hyN9UdV-hY}dl(3csg-GPqd#--FrotS%8 zb}fgLlpp-c)#%)N&%O6M=bm%!IUDmu?cc1yItz3@D3B~;C~>rs?K0YJMnjh2*sM|+ z^JJNkTtNsc8AqrGw$r9in1aKJ3EzZQOFny zdA7^Qr98cfk~P%LiUexWzGT*)WYNeAQ-bvp5!8A7g`m`}at5P)32Ts$WC!Jp11FJ> zC)+&ez~p#o!kvyMftgGCCzFY^mtZ44q68e&*qFs)DIp#jTP$uweHM$O!iRNYw=>Qq zf-s8Efu7zZ+FsoVPk3xfMh6I@hw^8KCPsd(DPK009g2hl zVubY(iSa&uP_{6Z%wVR6O~piKhZxQF`$O4|3BhMi1>EWIP;RO>)kcL)ZhtXdP9#Dh z_f#lWv^x5EZz-5g32}~e3w$IVD<#?{rUK&NgeT%{m-l2!Y{6qs^ZovwOm~n_GNCcK zmt~TKY0~OtY(#p{M9PVQ0G+dY%0uH^Ak^L+4)k+^H83>ArhB@RR4^^jk${PbdB!Gr zP8s*7tfFZsOQ$oj4!g^n@yl&dDIYCmC9&L>bqIUByWLYIf2c6X_m8tNVo*qxtOLT( zV9*p~BSD&s^buuiV%!&|qB7-*@=>lk?Fv(oR3_*n-0d-RxHryvyu3df3Lv*c-E7Dn zc7#Z;(`u7NyXr*3&j7o0J5w_=1vSpKMY$z4SHyeHHgGwB$row zq7r2kvyW8BR>N9kUKyCJ25*s9iW1Y6XNrnM@~wtgF~f6Ih$;7rIVRtgFY>$w;BVf5 zDpEy($tzm4u!)m>oLmrPhSpYIg+_fd+RAg$fA~CZEXs@&VHA=^It3L*kg+-ptF6Uv zsfG^2!wPe<0$0)LZs;q^Xsdbk26Oo8+$-`tLn-LF$>we*&qy3)MoOnhzQ`ar>C3j^ z;nl5uip1sFR)Zi@qQrBVYI9i4=yz=^WLz$?ooaWsb=Vz@)!i}D`u_wU86JVlWBOV| z46A=VvK6M+Aff^G)oliQv;|T^uGvaR5?KaAnnpP=_LeG!%uO-ds^$}w%vFcruj=QD zFM#SH7WDOqzzpQo0lC6Wsve^ea$J5W6GKdc&a$A)g#8{JD5ps%&d^Cb=W$h z-Go@aPGA{08r55CyV1a-WMph}8VyRhz^HXs1?VzT-GM?TA1`Kvlr`v!7b9gynIO8l zAZ_CBA-jTYwT&C3w1Je(h-F!qV(UQQsuWbyD?;o>!>SNeI4gjQYk*re0NMa>D`L5- z0Nn^k1$3_gqI;|Yrct>h2tSYt@WLAKwhh2`0KVx;V5Hc`1>Op86`qp*W+1m9vbm=5 z6R6uzC%mG>R42xbA28R>kZPR(2~E|>+`}mXSx{5DS}F>XSYRZDW8`|dD2_f2-eK%E~=&Ps!_P}+z+pCuPPLvQeCgb_rk?BPW! z2R4JhVfBA6>h;?Z(SRYYZAyrUx;!Z`|M_814>bbaxRH}RB$Z<&v6!dp#R5rjN?EU( zA|lcZ4wbO(dif^6@tWpp=c|#ax*Ke<=5Q^lqnO5So3z{X1~kO670nFFE&t`H8eeK& z8Xd)S00a$(09K>i2s4Oe2qVMl|6bJVKZ6JkQ4Jo~-hqgw%{kfTT$7Byf+T}-l5$M_^3l=E7$Zpxjh6K|4k3y`YKDf_8`KU6 zYS+o<1r8nr>*L@sFzLEM8YGoqMPyOWF?6cJL!lgGxnvZ<(dnfiiVrky%7@a%(&zIg`d~bWppN1ctx%kYP zfwy0tJO8^23nMG1zLq|}_aEE8doX^$B2NF{o#U@Pyyxo+(}!kf-|~I%0DWxceA5jJ z7al%!V&B~O@^8-lqGh&eY<|a(W97xUcW>O+@zyKNr;4|BtPITm(zQIeyjytuhbyh# zg$8l+;l=oYsUtfsUV8bAl6&n}JB6jw2S2~1W&go%;fFhS+(n;W-dp3B&f*pGKz6LO zudLf;{*lw0UNGqVmy}&k?|OA^?$F75o|rrPqk1!W-{)^la!RuB#Ihfz>X#B+r)C_q?2XImaGp;w(L6QB&|_E7NjtzW0onl<;(?|K4f&Yh=3{Vdv+rcr za!5(}gTJyj_ip#??(e;Q@9ldRApORluaULolB_37(MVHdl48oPH5#;<6k_O1vn?D>$xgs>~Iblf9PQr&j4p+{@yCqJ)KOE9~2wpHHEJ5Ie*kGi^ zfj5*!iv?RO7y%|5ag`#Wn3JG=BvAwoZgfDW(-kof_jNiOrld}1s_>x?YY39`8se~m z@FzRGJrTTRRVxy$7H5~Fi?iS1>FWpmtRyBq#bRe?+>%PeW}PeJ3PyvbUX!7h4t0?p zqC|#m$w;YS)gd#|I})9#c+l0#c^dTzCtv6^ckwa4rQ7S#he^uhwdsN}uOpYH2xnQ~ zSPSpV624BKIqm357zm?>Zl#E^Y}_>it$A<6v?M!WT~s{&U6Qf z(O|&ni4E-UCkV>e@AKq|Qprdg15^)T(v9?BJ6k%5XdIPDTZ`Z3)Fnqrj$wF9h@y1K zn6s}#Uy2s`3&zG4pVv$UO5st`JHU~nV_~o_;mUOMro;JQ*6Gx0bnR`r<>1mSM{T=I zjvtw95jXfkYgmIxAV4v!NOGbdiOnP>QcarWsJ%OAn>5aRM$Gfb&Z4}?Q<)}BARo^# zi7r&`<m0Q7O|odPt-F4$p|@4KuKlg#weuwq^w*e^}AQ+;kwH1QCv+Qauzd3wUYs(g`lem&Q&mlR*g)UqzwW zjabApiDs;Hl*;50hT}hJ7#v($8WwqmrJFQaA;Iw(CSGk0eKUUUZ-uzkN|_U8OG~TK zg!H!7p{D;Q_|V`G9A2ib!9=t4s|y$ke1!Sy6zi zDwiwOn6YjbDlsF?B1P*5^+U>f%p%)>rD2k|7VFJgO$H|;ZHq;#5z9Fw)np04u1&Z* za&b18k7uKL4;jq+%BC_w*zJ%uhKWgTYeR-_nOF}NfJ*ZYbPqgJyd z1Q*o`;6IlE*RKLJ1K;&jjMny0KDmLV652t z1>OL66|RzcGmu9xS+}O)1NgJ5PB=LpRVT*PKR5T!kW!rh30ta@xq}h2R8C6iQmM%C zTn_OfgM>OE&yP?Ev_YC|T&W>zD-5ZGG*tSPLb9}S1wu+ZwY%R#USpN)z`J50`ZiVX z2v^hqd&pI)oz+tn;Sya903hluKpw?pB}0D@59DBA$8cIfk zT7$cC*`i_w=a&DnRf;buFAWdNQ~(4`4goAhxfVtc$q+`GrS}m2svpNh4p9vrSMI_@ z(PAmJSe7Nrr?F&^j%Q>F2*vjqzOWt?Q9wMsR{(@xmr`q^hrddHg*J%4%S zn~xrzFfE|*>wA9p#%ser-e-9E;*`TM@c7J)So`qdgC`C=KX9ilmVfTZrC-L6U-;F) zmlodM_ml5k51!g~ed^lTg@M`V_G?cp{%~&b)vZTvpKbs8!ii@V{fn-H-?_Q#x1W3d z+VPw7U%Q@oYk_HDt_e{@!boyi8B+C1AFJF z^E)pGPQUc|w~xNDjSt_-_M*-LI3~& literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/pmgroup.pdn b/PROGMGR2/icons/src/pmgroup.pdn new file mode 100644 index 0000000000000000000000000000000000000000..f19f7da60dfbb3561980d74f17866eb14814db3c GIT binary patch literal 4191 zcmd^BYit|G5x%qdv}8-Qlelpk`$7c;8Yz4~7At-d{OpVj5IyPcMSepZzgu`UYMKlhRVaya7>=64?8^3=^2iTMpKa# zns=o#vnVtiDh`d7!ZYq!M?B3=N12QeP8HcuFr09whXRQnF76bHh4fIc=!IAxFV|gBR(07E;#kFQP<6Hx9C7BP5{HUWwSriUvJ zXY8@mEDAQQ|6{3?_5Qe9aRXp0o8h^Qmyno~k?cxUo#l+<|C1;|WWpXrWN> z`z@4hpx?F@EVi{M93V*i5X35O@P*c~36o@!;RPimDhZ@mLyW@oQfpCoa}f4YLA9)? z67ma3RV1d|OC{A@nP*2){b8|$1izq`%X)ynYXhptsud(C20XEumqWZ<6=lR38aF_% z-48?KYM5_ah0m!nlHy2VIIPo%f+{khBZ#&(^6pmX7+j(lFDq~qlWFUCUB*kT%@h2c zY>tCsxr|r^UoF`hK?0I^){2#$V9F}OaMGjBefyeA#}$be3cXZCW<{yY=UUBSx8mpa zR>=8$jED7j9eZ4EWbfOvzxV$MzJK3-I6Pr)!-Q(SW^60Mtj9zT>|5Im))=acgk94` zOA=EDL-u5OFm`7PL*^IIwwCc+BTMNp{4M?5@C8sa#Ddv~35?*?fzX@Wr0J23Gc%%O z$i{gAJ^__4bLMOs&GC>C@h0qElL?kuF=+d4g829_K^WnPT42LW+r>M=;kqS!iSLY~ zLddk0P+dO2e42!z7$)5Ex(%xWbRivZQZ`6|J%5?}W_vjw_ z6nQ-@vXeK&LI7@W-7(%!1MESXO!v1=HH2$)BLIMycL4c3ChJN1UOXVdz?!9Z;*R+X zn5-}OA|B{rb}&fVg?u0Kx0DgNr+N~DL03pqo(J5AQSYw)v+Ni zHWX}wjO!(b^fJo`c08%WNqU1vtTHUG)XkbH;v$DgD2BQ_<+p$&H|=b7z80C9yTKM~ z4maRZO6XnAd6&~n;Vwz6>KAcx`7c|w_|g(nHcOZQ2pS0itVOv6Mi9vmMpW}Xgumu) zOh|}o@VMatO!N-#yu-UDnfxo34ASuop@&fXjNuFGK@mN~)29U>c;AGhzn~PoZgY{5 zliJUZi9>lLNr=PKW|D*uB_KCLBaM{y0fO5d@`pi!2f_LzI1Eg>ZjkmybpRegT-g1z zsnOf~{tNBf4pXMD`@a&ont!)D|5WBXZ*R-jUR*YgzUvCVcJ#nG;?b+=U;AE`AF=-F z$-R$!&$ztw4bLa9ubf%gIXV9Gm7W97PcJDy$iMQl3y-~h`qfI|$B!*qk7OS__WH{7 zuZA!EV!3~E{_#sse-v3cTYv3CzFc|Y!~(yo`yZ#&>x2CE<>liap7`5w^pJ7!Lh!+B zuM8JXee|dT;dgjdUT^F-`2cJ9p-qu0qktg2S{gW%pFO8O{lgB=o zT7C7>!B2j7?BJW12j5)%;YHizIr5M9usa%uhMd=EUu!w-QF`kkszX=*c;K0rzwGh6 zb^b^C?z1D_@4j$f?~xOaw;$^McE`c*t9|b!t{zvnpl@Zno*n%2^~>i6&J3RJIQ6f4 z#|9S{PoC~vdgBfC{Osza_|Hdq8 MFa2iu=q}Lb-*Gq~$p8QV literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/pmitem.pdn b/PROGMGR2/icons/src/pmitem.pdn new file mode 100644 index 0000000000000000000000000000000000000000..7ac77f48152b24fe0ed340fafa33fdadb1535050 GIT binary patch literal 3864 zcmd^BU2GIp6rQ2G+Z`x^D1x9euEdv?{qJr`y4Bg8wk+*#x4YfaLdY_mxt$$4JG0JD zx66ZI;+qfp;HwFm5aXK(7$LrxXrcy)F(w9#1Wl0mAQ6okMWmiHv$ea3q7OcCCv)!H zbMJiT-gCY=X9|2ic7>(}>ynnO2{K_Dieyz&fmk%aR*524E%#X!n#3?u0Z^O5B9Znf zR&^RQims&s@n9?*4JLQTlfhU#9FGQu21VPn^xDv%Rkdq#Y+aL60cAQpQEY_AMrECY zmM@j7!(|zsGC1Vq43~p0JzUQkqmE`KUn+*PoMFbr#3X8p+GIJBh8LC&Hx>tGC(EcT zm4}zg#n}ue=XkDx8fbDM6bj)WyErvpb=HkaBYP*xpvK0HPlW2@1GsdrI9%N?!dl)$ z`$?V?rNw7P(O|k+Di_n!e6^62@@Zb@WPW(6D9p|zXCgIOPH2-dXU>dk%>-A7q^Huw zey*7(iw$0xl+?)nQeqDmo!&dXP!;&Z;k;el-^lHoNS8)xbxnz6k63xmZt`+ck+XJM zgx8z1YJ4m?LHOj%p2OqOOo7`+xWbV=B%>CeF^@(9()v#9_Z8X63(1R%5$*&&LCi=vjHVUMk64TwTPP&A9ztvs=UykH4^>`G*B z4{RTsu~o}9NJ=BNWe92?Td?O;MI0l|DSd%xDa}?@FTy|AfvSskjcAq+Ce|t@ub6e+ zB$Cf%mDk~%&!rplC%x{sO=9GTB}lNRtVL=j<)NsqE_!o2^f(f8Trn*?ir;@DD--t11yKpsN`iB^oglF$kNU7F3%6oN*|6;6Q6>$ubm8?qh4Fs2i#>*Y1vR z5U#s>VJ?{z`o;c4WOpo1!UMYx_WhsW2M-*?!&6Kb2)1=I;46ypg7BjH&OXC6zPeyQ zXf|?&AvDpEy%hzWy`fEEDo4nsw(+9-<$D1Bj&XKlfs#QkFx?<(wdrt{pR{w$c$4E&PTHh@0>7efeLWpk;%H?(s6wk&qPqdy zu>v*GH4+Q3EhC)Fxqv^c0B-02>_@^5y#-hOBcHP6_F8pWQ;zTDc10Bp%PMzp>Zb zX1nmGS!CY>?QfLaZJqbpbTSMHVv(HD-Chqf2$3|XsRBN9J z#Zn?(Qxvo?OnM+gcSJNtYP!)(tGc*=KEs=B-N&G39s}V;N8H_&$Ow-n)W~0d47#yK zz=?YlGcAYhR0SOO*=cM<8r864+sR07uAVq!HV?k3r8o0fI(WW5j(s zL3ksHrAT7MGW|JNM(Z#`d6A0$lD@beH{wM;{T%@@`hH-)Y*iC+rYe{P=g-G4k$GYm zM1pCCrjeo)re&4@* zzWUYj)57te4&8Y7xi0I2Z+=c5yYS=t@l!jlj=uEk=?m{&eD-9@i}#Qy|ny-@a6Z%)=x-w(|JHl+cXHI4LiSwW-1UaxJCC;h0Orh;xBvhE literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/progmgr.ico b/PROGMGR2/icons/src/progmgr.ico new file mode 100644 index 0000000000000000000000000000000000000000..1cb5e7c18837583edbe68af2aaf5c4979ba7da0e GIT binary patch literal 5414 zcmdT|zi(Vc5MC3+or1*P35k^FGUXwc6kHL}I*m(|R2CI^o!g~)FV!U_;(q`|`~xm1 zPoYW~NQEef^iZ&kBRj)4GdsKc-n}!15Cd!N?aq8VKX!I^cAuTwa&NoEVj}Hl*PZ*s zIX9n2`W@%K25);?>7UJrvp@}~tnZ@2V|ZYQoe+t`!$a_b zBgXMVu|ts{WiYz2G{YsBKz%S+GM;)K=B%6~Zrx0|K;4CS+qM_tP_YTO32eZZ=2O`g z{v{kPrZR*Vk*EgoY@mZDrRWeAt98DEmwI^-+op#XdZ}%R?)Pzow&lh5m9!!sqY~<6 zeYEFk|1KSUdZ&u2U_Y)ZxQ;v#{0O1lCprhNrH4l@k=pmv z#i7vj%KQZ9s1T|CQhrYDGnR*cu%`H}UHWyJ=BM$4jNxaiUE28&LuQ444Q65TkH4oE z-x7T_tKzJopY1!R`d7erh`yXvyj3T{mysC9@kvGSnfH(rp5jp{d(84Elas*l=Q!5O zFO(;GZB$tKnFcmM!|ZB zukoz~)W`KwN-~3ZA>PGtFl2sNyoVP+>~`$0!yWnlstFyE&{|aU(#e=LJTKkf!}HRq z{Ga$|i`8v|$m)+h1g@$rO#jcj@}$BX{@HdbF2tK}`JFjOy^H#9yfeFdvI%fQN-q*4VzOH}f6mgf5~>(?g^zet*<|1^5%^gL{4NHXZMK+Iu2?#v=-Tdqnj4Jvx7m$6EQ0qT58r_lTZCRfk^~7Ju;C z;&(&WPw0>QVmQWOY~=rTi)cDyKUqKK7Wu31@Vc4NbSi%4@n^pfee^M%KB9JRabUY= zE216nABrBCSH=9kUC_+$=B9yrUz4Rs^Z0Z_X_8F(dwjd!^LR~)cCYvC3OY&aW7|&G zEAag4xChFabok{=%JI=NOZrJqmn&njVWi|+Y%a^U*vR+|b~|xlBJgM~uY0?x zmjC9jt>SC7*eD|Z23o#nwowu4a10 zUz?{7Bc69T=kk~z^*o8Z90@%~8CN>vdTsY13|apUx-0ug^@Og*6mTcblpV_$xnr9tJ9B&B4n1oaeTU zdKLRzq5)g-UkGkr&K92A({CQ{jt(l}<06qLjhj}!Z3}wrTfVv5v3EQqfaW2Sv5T|_ ZIyaUDKpSZ{gAuFf4wV3Ar;b3!`UgYo*6{!U literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/progmgr.pdn b/PROGMGR2/icons/src/progmgr.pdn new file mode 100644 index 0000000000000000000000000000000000000000..750319525105ea4deb2bc64c206a23e210574704 GIT binary patch literal 6614 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 literal 0 HcmV?d00001 diff --git a/PROGMGR2/icons/src/progmgrd.pdn b/PROGMGR2/icons/src/progmgrd.pdn new file mode 100644 index 0000000000000000000000000000000000000000..c7891b50f834e45a7403e84cf48910f72a84f03c GIT binary patch literal 6457 zcmd^Bdwf$>o=>1HErMlHz)`fdJX|NxywgN!xn>zDaJs*aQ#ZG2WmUyimx!a7P`60VCU@I=*aSHNns2#Hf#`-RE1oace1%OSM zn^0@DJzz5cjve;^W+9u&D&(_xMTIN@11v3BVhIuf++DIHU<qbu5eS9I!K;)YAq^cgK7xQRWCQ#%Nx%X-a%*Y1S`WqP#z)w=T2P(F zcZGDNt|*wJ4uudzLMTOH77aJSRsL{!rL!jWjvaUFou6 ze2pe(_35!jl~zuas<@3JewmvUsB+WUT7jF1@MU2Fr5P&SO@^X?D5RocAwudmnj|5X zSYpMr4iCG`+$1$MIRyTQK#GYJbR)B=A*^P|j9Oi#)E1;^%ZrpsBUV#UF0p9%I*ATb zc*}GVg;R;xIRdTNWEDB3){s_Zsuni{b()%>5yd1Tn=$GLNW}I=5sjnK=mj3S4i{lY zku<0jh*(Ouh_A8Q>1;%ysX}#3fwj@24Kqr0RV+Fx!4R+CFY!p!J~yq2RfefldW}!u z#yqyD-EFT@haw6MlTb0tA|+NT5e0Fni6!M?d|xG2)uc4Y5hJgWNvmP|s-q!?QX;k~ z^ga|8}HQ#S{yJQhe>@X|5j2cA|qOS;f z_-3sSSC_KHQnT7_WuZ7%5U^-5PPLR!mMeYIGPyj6GxRb%$m5D7VY5hsb2&B-rj)4= zdyzT7sj$kBrs^trz=mp+I*!P|af_T42D49&s2E6PWvPNMDmU?*WthiT!8CIaQB*85 zOSKBQB3#1+E|*Bmn5@Rf275>K9t%crRUso!>emLU6r6CRM(meJD-eM%*i6=v5qvMqgf5T3O_F zXq`Nar88kwCX zR?gES4u)2N2dcFkxj!mzz-@{OOeT#Y;U*tL%2pwz9t?L{WPX_`ETUVY5w-!b;YC%L zRcvw?Lpmu(9xBsFcmk8ySwpzx6h)w2l1$h-*Tf`Vf zOwl4NP+cL{dejnC)PR-qC0;gNT84-?7Pg9Jq+^aqK%@EZP$)46%!~4`RlHjZ-lBYQ&=m;!(P9r84EW8iMfsXwgUfDF zpph!viF%4XL6<8N!ryrlDsBn7QBNQX2&UQziJkD`1ZvG1tG1cxTAVdjhI6i$-G2!Z zs9%W&%vP``c>r}2lne@G@?`3)iO?0WU{~0Q06a=|_U*a|0j3s?pP-vMJ{IFH7itNB zGENlAP!H<2TMEIZ4Q5vm1#tdHS+%v}Q*{Bq-GeR4cM}%e@3J>cGzX&)JU?%RhN2=f z*TUs71#Aw=;0x*&{eObj)z-noQ*tH)^2qp`18haf$pj=5vVYuWa88!j><6xyf%yIA z2s9+E-VTkOJApyiqv*^DK;C{` z3zH4iOb0yr4K*wQZ(I!kAJf9Vt_A$1jUo13L(IJykpmHD0AA4qL_R=DZ=8P(5u9Xv z-!=}QCZnlrJoi|hfn*_*EK>3hTL$GxaOU`L55M9|-8wxBc8LfVZB z<+d?K`aYR9)*ri7#%JDuNLQhZ#Xq5sHbJ-Mx>^{DcT8NN8`}o72Q@qU{)wV7FrY#g zr6&}CPR=|)ZcLaD2ANRx|LxeYf=_7x!DCf>GZs!fq#j(*qA>wMQ{jHM*)=|#1lGVe zX8|CY@T5OxI9Rc7y8N>UaQ9l#Ou}OJFn}-v6#ScFLW#O@e?;WMEly~4_&zfJ!aE>m zAsA#rQ~ta&U`%Cr%x?6D{~1%@l><&Z%}$8S7ANM%gC6S?+-tVj1CgAxDU`SsrNWCf z;Q%8A1qDBSGvg6*Hf|~ z5NuSK0_i;YH5|cQfMN8=_?z}N4GgF-FQCV>76FpU;fFc=YnrK_0?kl6kWi>FWzv9j zILZg)2Y@iN)Z^J*&si$fDO3AW+pW0U%hNA+KBr7s1=BFs8pCl zX}iKNbqe$vv~IfnLjI?yFvg(usW7CVNpBd03d1EWgVAw|40=8-gO0vgb{nV-fSGQS z6nU%Qg$ml#@7Ghe|298+#lW}szO&)`?j5S9Mfq=PnfrF&NAGKm&$!qlKDm8SJ-&DO zy{G=?zZ31jVAr0(UFyPQTTlyA?{pkv# zWzMK`(WQsmiq&1cd$QO=3r;(yFHK$Ojp03#3&Wv5Bwkw~Jgb=QsQZxo_2`c0-bpkHAi znW+<_Mkl$jhD}edO|5Z;&h{M7!IP&3o_alX`jm-$VRZfRPX`we{N$d_j`n2x@X4#S z=+fGRqI>n%!VB?>TZMJIb`E`3OD^T!(_4+g-lbhT<%0`)=A0wf^{ssHlb0|5wXeUU zJ9l;c2jq)`@r#q(HTuuxNoz3s8`8Y2(S)AxOl$_TG$(A|s<+3$@?yF5+9mz;N`Yd-($#UWL_ER+B z{`tO^Dbz;v9P=zSJbYFakXaVllj>P2EHve;obhv4$p|c zk^N9A^qUR8Ijhdz-f`irF8=B}KYYWom}aS1hnyJM*mKZxD%n9doP444z!xfEf9=q~ znt0ctyFeqCj-C#Ywq%+f}YwJ^8Cw5VsG7$g4Zzpx!B*6t$T!j>dqAqyT9jd zjt$u`O;AB)hUPK^+{*%JVA*eFM$HSH9Y0I5v{ER;?I_AO3*z zVr<3yM33W->oycUl=b)*?}wXvE86*6QYSAD{&88-xRGpBU+!7<@7Csbd+TQo?yi^= z-!OU8w!Y2h?zY|jQ_uSEJHDFEE8cqKR)2dZ`kQ+Dlljx6p};fUN7qYE{7G}1@?|^u z`^GnFW_OnCSbpq*bwt~-r~7-v*1priyQ|I=uS0)z-lx*&pk1 ztl*KIOUbnZ=;+)}a$iqudL=op{mHE6HgaQ$eLs1+`OOGf`&Hb08ow&eNwP;?x-wj} z?DSUo!{i@El>;B099%ry`L=V%Ui;;kVf3@FV}q-wZk;vnbKmJ%kC~G6!Qy=^ z<=yJyXO?{b*wTAkgRP0VJ&}^d3H6~)+WGi5iP-K`qGWb(L99FZ+++23lG!^ie)!sd zbhQw->)j+iw0O~_t>^Nb2bUi1U3HKme2I9g_puZiw|&#fB}?2p znOYkT*k%r%5w;7j3eV@A7Y=uhL_b=c%55HO>2Dcr8D2R|ulqLkExA6%AkC@$$(BTJ zTZ~VBoopG&Jw<+%x@{o#K6$0PHx@^8uU@#t_>?OXjNhT1x-WmmZ_OPof^{KPukzhyNGV^oEj<>ex zM?1I8DNV#9Ysu{kv03+%^=*5)V)My&1~w)w-NIvu9_3#BH_6Q;Ys2~N&2z49?qFSf z)0?VKUK|) +#define STRICT +#include +#undef STRICT +#include "resource.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +/* Dialogs */ +// Program Group +DLG_GROUP DIALOG 0, 0, 256, 96 +STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_POPUP +EXSTYLE WS_EX_WINDOWEDGE +FONT 8, "Ms Shell Dlg 2" +CAPTION "Program Group" +{ + EDITTEXT IDD_NAME, 56, 19, 108, 14, WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_LEFT + AUTOCHECKBOX "Create group for all users", IDD_COMMGROUP, 14, 40, 94, 8, WS_TABSTOP | WS_DISABLED, WS_EX_LEFT + PUSHBUTTON "Change Icon...", IDD_CHICON, 185, 47, 55, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "OK", IDD_OK, 145, 75, 50, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "Cancel", IDD_CANCEL, 199, 75, 50, 14, WS_TABSTOP, WS_EX_LEFT + // The following controls shouldn't be directly interacted with. + CONTROL "", IDD_STAT_ICON, WC_STATIC, SS_ICON | SS_CENTERIMAGE, 202, 19, 21, 20, WS_EX_LEFT + LTEXT "Name:", 32, 16, 22, 22, 9, SS_LEFT, WS_EX_LEFT + GROUPBOX "Properties", 33, 7, 7, 162, 61, 0, WS_EX_LEFT + GROUPBOX "Icon", 34, 176, 7, 73, 61, 0, WS_EX_LEFT +} + +// Program Item +DLG_ITEM DIALOG 0, 0, 256, 167 +STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_POPUP +EXSTYLE WS_EX_WINDOWEDGE +FONT 8, "Ms Shell Dlg 2" +CAPTION "Program Item" +{ + EDITTEXT IDD_NAME, 56, 19, 108, 14, WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_LEFT + EDITTEXT IDD_PATH, 16, 47, 94, 14, WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_LEFT + PUSHBUTTON "Browse...", IDD_BROWSE, 114, 47, 50, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "Change Icon...", IDD_CHICON, 185, 47, 55, 14, WS_TABSTOP, WS_EX_LEFT + AUTOCHECKBOX "Use different working directory", IDD_WORKDIR, 14, 87, 111, 8, WS_TABSTOP, WS_EX_LEFT + EDITTEXT IDD_WORKPATH, 80, 99, 106, 14, WS_TABSTOP | WS_DISABLED | ES_AUTOHSCROLL, WS_EX_LEFT + PUSHBUTTON "Browse...", IDD_BROWSE2, 190, 99, 50, 14, WS_TABSTOP | WS_DISABLED, WS_EX_LEFT + CONTROL "", IDD_HOTKEY, HOTKEY_CLASS, WS_TABSTOP, 56, 117, 184, 14, WS_EX_LEFT + PUSHBUTTON "OK", IDD_OK, 145, 146, 50, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "Cancel", IDD_CANCEL, 199, 146, 50, 14, WS_TABSTOP, WS_EX_LEFT + // The following controls shouldn't be directly interacted with. + CONTROL "", IDD_STAT_ICON, WC_STATIC, SS_ICON | SS_CENTERIMAGE, 202, 19, 21, 20, WS_EX_LEFT + LTEXT "Name:", 32, 16, 22, 22, 9, SS_LEFT, WS_EX_LEFT + LTEXT "Directory:", 34, 16, 37, 31, 9, SS_LEFT, WS_EX_LEFT + LTEXT "Hotkey:", 35, 16, 120, 26, 9, SS_LEFT, WS_EX_LEFT + LTEXT "Directory:", IDD_STAT_WORKDIR, 26, 102, 31, 9, WS_DISABLED | SS_LEFT, WS_EX_LEFT + GROUPBOX "Properties", 36, 7, 7, 162, 61, 0, WS_EX_LEFT + GROUPBOX "Icon", 37, 176, 7, 73, 61, 0, WS_EX_LEFT + GROUPBOX "Advanced", 38, 7, 75, 242, 64, 0, WS_EX_LEFT +} + +// Power and Shutdown +DLG_POWER DIALOG 0, 0, 256, 167 +STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_SYSMENU | WS_POPUP +EXSTYLE WS_EX_WINDOWEDGE +FONT 8, "Ms Shell Dlg 2" +CAPTION "Shut Down" +{ + EDITTEXT IDD_NAME, 56, 19, 108, 14, WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_LEFT + EDITTEXT IDD_PATH, 16, 47, 94, 14, WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_LEFT + PUSHBUTTON "Browse...", IDD_BROWSE, 114, 47, 50, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "Change Icon...", IDD_CHICON, 185, 47, 55, 14, WS_TABSTOP, WS_EX_LEFT + AUTOCHECKBOX "Use different working directory", IDD_WORKDIR, 14, 87, 111, 8, WS_TABSTOP, WS_EX_LEFT + EDITTEXT IDD_WORKPATH, 80, 99, 106, 14, WS_TABSTOP | WS_DISABLED | ES_AUTOHSCROLL, WS_EX_LEFT + PUSHBUTTON "Browse...", IDD_BROWSE2, 190, 99, 50, 14, WS_TABSTOP | WS_DISABLED, WS_EX_LEFT + CONTROL "", IDD_HOTKEY, HOTKEY_CLASS, WS_TABSTOP, 56, 117, 184, 14, WS_EX_LEFT + PUSHBUTTON "OK", IDD_OK, 145, 146, 50, 14, WS_TABSTOP, WS_EX_LEFT + PUSHBUTTON "Cancel", IDD_CANCEL, 199, 146, 50, 14, WS_TABSTOP, WS_EX_LEFT + // The following controls shouldn't be directly interacted with. + CONTROL "", IDD_STAT_ICON, WC_STATIC, SS_ICON | SS_CENTERIMAGE, 202, 19, 21, 20, WS_EX_LEFT + LTEXT "Name:", 32, 16, 22, 22, 9, SS_LEFT, WS_EX_LEFT + GROUPBOX "Properties", 36, 7, 7, 162, 61, 0, WS_EX_LEFT +} diff --git a/PROGMGR2/lang/res_en-US.rc b/PROGMGR2/lang/res_en-US.rc new file mode 100644 index 0000000..60ef863 --- /dev/null +++ b/PROGMGR2/lang/res_en-US.rc @@ -0,0 +1,160 @@ +/* * * * * * * *\ + RES_EN-US.RC - + Copyright (c) 2024 Vortesys, Brady McDermott + LANGUAGE - + English, US + CREDITS - + freedom7341 + DESCRIPTION - + This file contains the language-specific + resources for the Program Manager. + ** NO DEPENDENCIES ** + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Necessary Evil */ +#define APSTUDIO_HIDDEN_SYMBOLS +#include +#include "resource.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +/* Accelerator Table */ +IDA_ACCELS ACCELERATORS +{ + "N", IDM_FILE_NEW, VIRTKEY, CONTROL +} + +/* Menus and Commands */ +// Main Menu +IDM_MAIN MENU +{ + POPUP "&File" + { + POPUP "&New" + { + MENUITEM "Program &Group", IDM_FILE_NEW_GROUP + MENUITEM "Program &Item", IDM_FILE_NEW_ITEM + } + MENUITEM SEPARATOR + MENUITEM "&Open", IDM_FILE_OPEN + MENUITEM "&Move", IDM_FILE_MOVE + MENUITEM "&Copy", IDM_FILE_COPY + MENUITEM "&Delete", IDM_FILE_DELETE + MENUITEM "&Properties", IDM_FILE_PROPS + MENUITEM SEPARATOR + MENUITEM "&Run...", IDM_FILE_RUN + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_FILE_EXIT + } + POPUP "&Options" + { + MENUITEM "&Auto Arrange", IDM_OPTIONS_AUTOARRANGE + MENUITEM "&Minimize on Use", IDM_OPTIONS_MINONRUN + MENUITEM "Always &on Top", IDM_OPTIONS_TOPMOST + MENUITEM "Show &Name on Titlebar", IDM_OPTIONS_SHOWUSERNAME + MENUITEM "&Save Settings on Exit", IDM_OPTIONS_SAVESETTINGS + MENUITEM SEPARATOR + MENUITEM "Save Settings &Now", IDM_OPTIONS_SAVENOW + } + POPUP "&Window" + { + MENUITEM "&Cascade", IDM_WINDOW_CASCADE + MENUITEM "&Tile Vertically", IDM_WINDOW_TILE + MENUITEM "Tile &Horizontally", IDM_WINDOW_TILEHORIZONTALLY + MENUITEM "&Arrange Icons", IDM_WINDOW_ARRANGEICONS + } + POPUP "&Help" + { + MENUITEM "&View Internet Help", IDM_HELP_INDEX + MENUITEM SEPARATOR + MENUITEM "&About Program Manager II", IDM_HELP_ABOUT + } +} + +IDM_DESK MENU PRELOAD +{ + POPUP "Context Menu" + { + MENUITEM "&View", IDM_DESK_VIEW + MENUITEM "S&ort by", IDM_DESK_SORT + MENUITEM "&Run Program", IDM_FILE_RUN + MENUITEM "&Task Manager", IDM_TASKMGR + MENUITEM SEPARATOR + MENUITEM "S&creen Resolution", IDM_DESK_SCREENRES + MENUITEM "Pe&rsonalize", IDM_DESK_PERSONALIZE + } +} + + +// Context Menus +IDM_ITEM MENU PRELOAD // Program Item +{ + POPUP "Context Menu" + { + MENUITEM "&Open", IDM_FILE_OPEN + MENUITEM "&Move to", IDM_FILE_MOVE + MENUITEM "&Copy to", IDM_FILE_COPY + MENUITEM "&Delete", IDM_FILE_DELETE + MENUITEM SEPARATOR + MENUITEM "&Properties", IDM_FILE_PROPS + } +} +IDM_GROUP MENU PRELOAD // Program Group + { + POPUP "Context Menu" + { + MENUITEM "&New", IDM_FILE_NEW + // MENUITEM "&Delete", IDM_FILE_DELETE + // MENUITEM SEPARATOR + // MENUITEM "&Properties", IDM_FILE_PROPS + } +} + +/* String Table */ +STRINGTABLE +{ + // Application +#ifndef _DEBUG + IDS_APPTITLE, "Program Manager II" // 64 +#else + IDS_APPTITLE, "Program Manager II [DEBUG]" // 64 +#endif + IDS_PMCLASS, "progmgr" // 16 + IDS_DTCLASS, "progman" // 16 + IDS_GRPCLASS, "pmgroup" // 16 + IDS_WEBSITE, "https://Vortesys.github.io/progmgr/" // 64 + + // Menu commands + IDS_RUN "R&un..." + IDS_TASKMGR "&Task Manager" + IDS_EXIT "E&xit" + IDS_SHUTDOWN "S&hutdown..." + + // Dialog strings + IDS_DLG_OK "OK" + IDS_DLG_CANCEL "Cancel" + IDS_DLG_BROWSE "Browse..." + + // Icon section strings + IDS_DLG_ICON "Icon" + IDS_DLG_CHICON "Change Icon..." + + // Properties section strings + IDS_DLG_PROPS "Properties" + IDS_DLG_NAME "Name:" + IDS_DLG_DIRECTORY "Directory:" + IDS_DLG_COMMGRP "Create group for all users" + + // Advanced section strings + IDS_DLG_ADVANCED "Advanced" + IDS_DLG_WORKDIR "Use different working directory" + IDS_DLG_HOTKEY "Hotkey:" + + // Dialog title strings + IDS_DLT_GRP_PROPS "Group Properties" // 32 + IDS_DLT_GRP_NEW "New Group" // 16 + IDS_DLT_ITEM_PROPS "Item Properties" // 32 + IDS_DLT_ITEM_NEW "New Item" // 16 + IDS_DLT_POWER "Shut Down" // [Computer Name] 16 + 16 +} diff --git a/PROGMGR2/progmgr.c b/PROGMGR2/progmgr.c new file mode 100644 index 0000000..3ba8d95 --- /dev/null +++ b/PROGMGR2/progmgr.c @@ -0,0 +1,221 @@ +/* * * * * * * *\ + PROGMGR.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's main file, now with extra wWinMain! + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#define SECURITY_WIN32 +#include +#include "progmgr.h" +#include "group.h" +#include "resource.h" +#include "registry.h" + +/* Variables */ +// Global +#ifdef _DEBUG +BOOL g_bIsDebugBuild = TRUE; +#else +BOOL g_bIsDebugBuild = FALSE; +#endif +BOOL g_bIsDefaultShell = FALSE; +// Handles +HINSTANCE g_hAppInstance; +HWND g_hWndProgMgr = NULL; +// Icons +HICON g_hProgMgrIcon = NULL; +HICON g_hGroupIcon = NULL; +// Global Strings +WCHAR 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. +\* * * */ +int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) +{ + MSG msg = { 0 }; + HANDLE hAccel; + HMENU hMenu; + HMENU hSystemMenu; + WNDCLASS wc = { 0 }; + WCHAR szBuffer[MAX_PATH]; + RECT rcRoot; + POINT ptOffset = { 0 }; + + // Initialize the instance + g_hAppInstance = hInstance; + + // Create Strings + 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)); + + // Get Desktop background color + //CreateSolidBrush(GetBackgroundColor + + // Register the Frame Window Class + wc.lpfnWndProc = WndProc; + 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 = g_szClass; + + if (!RegisterClass(&wc)) + return FALSE; + + // Load the Accelerator table + hAccel = LoadAccelerators(g_hAppInstance, MAKEINTRESOURCE(IDA_ACCELS)); + if (!hAccel) + return FALSE; + + // Perform Registry actions, close if registry is inaccessible. + if (!InitializeRegistryKeys()) + return FALSE; + + g_bIsDefaultShell = IsProgMgrDefaultShell(); + + // Load configuration, but don't load groups yet + if(LoadConfig(TRUE, TRUE, FALSE) != RCE_SUCCESS) + return FALSE; + + // Get size of the root HWND + GetWindowRect(GetDesktopWindow(), &rcRoot); + + // Get the initial window offset + SystemParametersInfo(SPI_ICONHORIZONTALSPACING, 0, &ptOffset.x, 0); + SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, &ptOffset.y, 0); + + // Create main window with a default size + // TODO: i pulled 320x240 out of my ass, make this dynamic later + if ((g_hWndProgMgr = CreateWindowW(wc.lpszClassName, g_szAppTitle, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + rcRoot.left + ptOffset.x, rcRoot.top + ptOffset.y, + rcRoot.left + ptOffset.x + 320, rcRoot.top + ptOffset.y + 240, + 0, 0, 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(g_hWndProgMgr, NULL, + rcMainWindow.left, rcMainWindow.top, + rcMainWindow.right - rcMainWindow.left, + rcMainWindow.bottom - rcMainWindow.top, SWP_NOZORDER); + + // Load the menus... + hMenu = GetMenu(g_hWndProgMgr); + hSystemMenu = GetSystemMenu(g_hWndProgMgr, FALSE); + + // Update relevant parts of the window + UpdateChecks(bAutoArrange, IDM_OPTIONS, IDM_OPTIONS_AUTOARRANGE); + UpdateChecks(bMinOnRun, IDM_OPTIONS, IDM_OPTIONS_MINONRUN); + UpdateChecks(bTopMost, IDM_OPTIONS, IDM_OPTIONS_TOPMOST); + UpdateChecks(bShowUsername, IDM_OPTIONS, IDM_OPTIONS_SHOWUSERNAME); + UpdateChecks(bSaveSettings, IDM_OPTIONS, IDM_OPTIONS_SAVESETTINGS); + + UpdateWindowTitle(); + + // Update settings based on their values + if (bTopMost) + SetWindowPos(g_hWndProgMgr, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + + if (g_bIsDefaultShell) + { + // Modify the context menus since we're the default shell + DeleteMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND); + + 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(g_hAppInstance, IDS_RUN, szBuffer, ARRAYSIZE(szBuffer)); + InsertMenu(hSystemMenu, 6, MF_BYPOSITION | MF_STRING, IDM_FILE_RUN, szBuffer); + + LoadString(g_hAppInstance, IDS_TASKMGR, szBuffer, ARRAYSIZE(szBuffer)); + InsertMenu(hSystemMenu, 6, MF_BYPOSITION | MF_STRING, IDM_TASKMGR, szBuffer); + + // Create the desktop window... + // CreateDesktopWindow(); + } + + // Create the frame window + if (!InitializeGroups()) + return FALSE; + + while (GetMessage(&msg, NULL, 0, 0) > 0) + { + if (!TranslateMDISysAccel(hWndMDIClient, &msg) && + !TranslateAccelerator(g_hWndProgMgr, hAccel, &msg)) + { + DispatchMessage(&msg); + } + } + + 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 + +*/ \ No newline at end of file diff --git a/PROGMGR2/progmgr.exe.manifest b/PROGMGR2/progmgr.exe.manifest new file mode 100644 index 0000000..2720cbe --- /dev/null +++ b/PROGMGR2/progmgr.exe.manifest @@ -0,0 +1,28 @@ + + + + + True/PM + PerMonitorV2, PerMonitor + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PROGMGR2/progmgr.h b/PROGMGR2/progmgr.h new file mode 100644 index 0000000..4869e10 --- /dev/null +++ b/PROGMGR2/progmgr.h @@ -0,0 +1,61 @@ +/* * * * * * * *\ + PROGMGR.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's primary header file. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#pragma once +#pragma comment(lib, "ComCtl32.lib") +#pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "Shell32.lib") +#pragma comment(lib, "Secur32.lib") +#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) +// RunFileDlg flags +#define RFF_NOBROWSE 0x0001 // Removes the browse button +#define RFF_NODEFAULT 0x0002 // No default item selected +#define RFF_CALCDIRECTORY 0x0004 // Calculates the working directory from the file name +#define RFF_NOLABEL 0x0008 // Removes the edit box label +#define RFF_NOSEPARATEMEM 0x0020 // Removes the Separate Memory Space check box, NT only +// RunFileDlg notification return values +#define RF_OK 0x0000 // Allow the application to run +#define RF_CANCEL 0x0001 // Cancel the operation and close the dialog +#define RF_RETRY 0x0002 // Cancel the operation, but leave the dialog open + +/* Global Variables */ +extern BOOL g_bIsDefaultShell; +// Handles +extern HINSTANCE g_hAppInstance; +extern HWND g_hWndProgMgr; +// Icons +extern HICON g_hProgMgrIcon; +extern HICON g_hGroupIcon; +// Strings +extern WCHAR g_szAppTitle[64]; +extern WCHAR g_szProgMgr[]; +extern WCHAR g_szWebsite[64]; +extern WCHAR g_szClass[16]; +// Permissions +extern BOOL g_bPermAdmin; // Has Administrator permissions +extern BOOL g_bPermGuest; // Has Guest permissions +extern BOOL g_bPermPower; // Has power option permissions + +/* Function Prototypes */ +BOOL UpdatePermissions(VOID); +// SYSINT.C +BOOL RunFileDlg(HWND hWndOwner, HICON hIcon, LPWSTR lpszDir, LPWSTR lpszTitle, LPWSTR lpszDesc, DWORD dwFlags); +BOOL ExitWindowsDialog(HWND hWndOwner); +BOOL SetShellWindow(HWND hWndShell); +// WNDPROC.C +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); diff --git a/PROGMGR2/progmgr.vcxproj b/PROGMGR2/progmgr.vcxproj new file mode 100644 index 0000000..b141fbe --- /dev/null +++ b/PROGMGR2/progmgr.vcxproj @@ -0,0 +1,201 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b76b940d-b61a-456e-8569-72f64cf91afb} + progmgr + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\ + false + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\ + false + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\ + false + + + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\ + false + + + + Level3 + true + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + $(OutDir)$(TargetName)$(TargetExt) + 5.02 + $(IntDir)$(TargetName)$(TargetExt).manifest + + + _DEBUG;%(PreprocessorDefinitions) + + + + + Level3 + true + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + $(OutDir)$(TargetName)$(TargetExt) + 5.02 + $(IntDir)$(TargetName)$(TargetExt).manifest + + + + + Level3 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + $(OutDir)$(TargetName)$(TargetExt) + 5.02 + $(IntDir)$(TargetName)$(TargetExt).manifest + + + _DEBUG;%(PreprocessorDefinitions) + + + + + Level3 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + $(OutDir)$(TargetName)$(TargetExt) + 5.02 + $(IntDir)$(TargetName)$(TargetExt).manifest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PROGMGR2/progmgr.vcxproj.filters b/PROGMGR2/progmgr.vcxproj.filters new file mode 100644 index 0000000..0b86c3d --- /dev/null +++ b/PROGMGR2/progmgr.vcxproj.filters @@ -0,0 +1,84 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {71dbbd6d-c82a-4fac-a0ff-74be88190f82} + + + {2a11d118-5a5c-4681-86dc-31de4f0251ff} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + Resource Files\en-US + + + Resource Files\en-US + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/PROGMGR2/registry.c b/PROGMGR2/registry.c new file mode 100644 index 0000000..223cc6f --- /dev/null +++ b/PROGMGR2/registry.c @@ -0,0 +1,388 @@ +/* * * * * * * *\ + REGISTRY.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's registry and settings related functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include "progmgr.h" +#include "group.h" +#include "registry.h" + +/* Variables */ +// Global HKEYs +HKEY hKeyProgramManager = NULL; +HKEY hKeyProgramGroups = NULL; +HKEY hKeySettings = NULL; +// Global Values +BOOL bSaveSettings; +BOOL bShowUsername; +BOOL bTopMost; +BOOL bMinOnRun; +BOOL bAutoArrange; +DWORD dwSettingsMask = { + PMS_SAVESETTINGS | + PMS_SHOWUSERNAME | + !PMS_TOPMOST | + !PMS_MINONRUN | + PMS_AUTOARRANGE +}; +RECT rcMainWindow; +// Registry Subkeys +PWSTR pszProgramGroups = TEXT("Program Groups"); +PWSTR pszSettings = TEXT("Settings"); +// Settings Subkeys +PWSTR pszSettingsWindow = TEXT("Window"); +PWSTR pszSettingsMask = TEXT("SettingsMask"); +// Permissions (Global) + +/* Functions */ + +/* * * *\ + InitializeRegistryKeys - + Takes the relevant registry keys and turns them + into valid and usable handles. + RETURNS - + TRUE if successful, FALSE if unsuccessful. +\* * * */ +BOOL InitializeRegistryKeys(VOID) +{ + 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, g_szProgMgr, 0, + KEY_READ | KEY_WRITE, NULL, &hKeyProgramGroups, NULL); + RegCreateKeyEx(hKeyProgramManager, pszSettings, 0, g_szProgMgr, 0, + KEY_READ | KEY_WRITE, NULL, &hKeySettings, NULL); + + return TRUE; + } + return FALSE; +} + +/* * * *\ + IsProgMgrDefaultShell - + Detects if Program Manager is the default shell. + RETURNS - + TRUE if Program Manager is the default shell, + FALSE if otherwise or an error occurs. +\* * * */ +BOOL IsProgMgrDefaultShell(VOID) +{ + HKEY hKeyWinlogon; + 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, TEXT("Shell"), 0, &dwType, + (LPBYTE)szShell, &dwBufferSize) == ERROR_SUCCESS) + { + if (StrStr(szShell, g_szProgMgr)) + { + // ProgMgr detected >:) + RegCloseKey(hKeyWinlogon); + return TRUE; + } + else + { + // Inferior shell detected. + RegCloseKey(hKeyWinlogon); + return FALSE; + } + } + } + else + { + // Assume that we're the shell... just incase. + RegCloseKey(hKeyWinlogon); + return TRUE; + } + // No registry access. + return FALSE; +} + +/* * * *\ + RegistrySaveGroup - + Saves a group structure to registry. + RETURNS - + RCE_* configuration error value +\* * * */ +DWORD RegistrySaveGroup(_In_ PGROUP pg) +{ + DWORD dwConfigStatus = RCE_SUCCESS; + + // If the pointer is invalid then fail out + if (pg == NULL) + return RCE_FAILURE; + + // Save group + UpdateGroup(pg); + if (!RegSetValueEx(hKeyProgramGroups, pg->szName, 0, REG_BINARY, + (const BYTE*)pg, sizeof(*pg)) == ERROR_SUCCESS) + dwConfigStatus = dwConfigStatus && RCE_GROUPS; + + return dwConfigStatus; +} + +/* * * *\ + SaveConfig - + Finds and collapses all settings + and saves them to the registry. + RETURNS - + RCE_* configuration error value +\* * * */ +DWORD SaveConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups, _In_ BOOL bExit) +{ + DWORD dwConfigStatus = RCE_SUCCESS; + + if (bSettings) + { + // Shrink the settings into the bitmask and save it + // There's definitely a better way to do this but... + // TODO: do this more efficiently + dwSettingsMask = + (bAutoArrange && PMS_AUTOARRANGE) * PMS_AUTOARRANGE | + (bMinOnRun && PMS_MINONRUN) * PMS_MINONRUN | + (bTopMost && PMS_TOPMOST) * PMS_TOPMOST | + (bShowUsername && PMS_SHOWUSERNAME) * PMS_SHOWUSERNAME | + (bSaveSettings && PMS_SAVESETTINGS) * PMS_SAVESETTINGS; + + if (!RegSetValueEx(hKeySettings, pszSettingsMask, 0, REG_DWORD, + (const BYTE*)&dwSettingsMask, sizeof(dwSettingsMask)) == ERROR_SUCCESS) + dwConfigStatus = dwConfigStatus && RCE_SETTINGS; + } + + if (bPos) + { + WINDOWPLACEMENT wpProgMgr = { 0 }; + RECT rcWindow; + + // Get and save window position + wpProgMgr.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(g_hWndProgMgr, &wpProgMgr); + CopyRect(&rcWindow, &wpProgMgr.rcNormalPosition); + + if (!RegSetValueEx(hKeySettings, pszSettingsWindow, 0, REG_BINARY, + (const BYTE*)&rcWindow, sizeof(rcWindow)) == ERROR_SUCCESS) + dwConfigStatus = dwConfigStatus && RCE_POSITION; + } + + if (bGroups) + { + 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 + from the registry. + RETURNS - + RCE_* configuration error value +\* * * */ +DWORD LoadConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups) +{ + DWORD dwConfigStatus = RCE_SUCCESS; + + if (bSettings) + { + DWORD dwBufferSize = sizeof(dwSettingsMask); + DWORD dwType = REG_DWORD; + + // Load settings bitmask + if (!RegQueryValueEx(hKeySettings, pszSettingsMask, 0, &dwType, + (LPBYTE)&dwSettingsMask, &dwBufferSize) == ERROR_SUCCESS) + dwConfigStatus = dwConfigStatus && RCE_SETTINGS; + + // Apply bitmask to booleans + bAutoArrange = (dwSettingsMask & PMS_AUTOARRANGE); + bMinOnRun = (dwSettingsMask & PMS_MINONRUN); + bTopMost = (dwSettingsMask & PMS_TOPMOST); + bSaveSettings = (dwSettingsMask & PMS_SAVESETTINGS); + bShowUsername = (dwSettingsMask & PMS_SHOWUSERNAME); + } + + if (bPos) + { + DWORD dwRectBufferSize = sizeof(rcMainWindow); + DWORD dwType = REG_BINARY; + + // Load window position + if (!RegQueryValueEx(hKeySettings, pszSettingsWindow, 0, &dwType, + (LPBYTE)&rcMainWindow, &dwRectBufferSize) == ERROR_SUCCESS) + dwConfigStatus = dwConfigStatus && RCE_POSITION; + } + + if (bGroups) + { + DWORD dwBufferSize = sizeof(dwSettingsMask); + DWORD dwType = REG_BINARY; + UINT cGroupVals = 0; + + OutputDebugString(TEXT("REGISTRY.C: Loading groups...\n")); + + // Get the num of group values, if we fail then ABORT! + if (!(RegQueryInfoKey(hKeyProgramGroups, NULL, NULL, NULL, + NULL, NULL, NULL, &cGroupVals, + NULL, NULL, NULL, NULL) == ERROR_SUCCESS)) + { + dwConfigStatus = dwConfigStatus && RCE_SETTINGS; + + // I can get away with returning here upon + // failure since this is the last one + OutputDebugString(TEXT("REGISTRY.C: Failed to get # of values!\n")); + return dwConfigStatus; + } + + // Enumerate through the registry values + if (cGroupVals) + { + DWORD i = 0; + + for (i = 0; i < cGroupVals; i++) + { + WCHAR szGroupValName[MAX_TITLE_LENGTH] = TEXT(""); + UINT cbGroupValName = MAX_TITLE_LENGTH; + 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; +} diff --git a/PROGMGR2/registry.h b/PROGMGR2/registry.h new file mode 100644 index 0000000..5af71c0 --- /dev/null +++ b/PROGMGR2/registry.h @@ -0,0 +1,55 @@ +/* * * * * * * *\ + REGISTRY.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's header file for registry related functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#pragma once + +/* Defines */ +#define HKEYMAXLEN 261 +// Key Paths +#define WINLOGON_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon") +// #define PROGMAN_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager") +// #define WINDOWS_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows") +#define PROGMGR_KEY TEXT("Software\\Vortesys\\Program Manager II") +// Registry configuration error values (DWORD) +#define RCE_SUCCESS 0x0000000 +#define RCE_FAILURE 0x0000001 +#define RCE_SETTINGS 0x0000002 +#define RCE_POSITION 0x0000004 +#define RCE_GROUPS 0x0000008 +// Settings values (DWORD) +#define PMS_AUTOARRANGE 0x00000001 +#define PMS_MINONRUN 0x00000002 +#define PMS_TOPMOST 0x00000004 +#define PMS_SHOWUSERNAME 0x00000008 +#define PMS_SAVESETTINGS 0x00000010 + +/* Global Variables */ +// HKEYs +extern HKEY hKeyProgramManager; +extern HKEY hkeyProgramGroups; +extern HKEY hKeySettings; +// Settings +extern BOOL bAutoArrange; +extern BOOL bMinOnRun; +extern BOOL bTopMost; +extern BOOL bShowUsername; +extern BOOL bSaveSettings; +extern RECT rcMainWindow; + +/* Function Prototypes */ +BOOL InitializeRegistryKeys(VOID); +BOOL IsProgMgrDefaultShell(VOID); +// Groups +DWORD RegistrySaveGroup(_In_ PGROUP pg); +// Settings +DWORD SaveConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups, _In_ BOOL bExit); +DWORD LoadConfig(_In_ BOOL bSettings, _In_ BOOL bPos, _In_ BOOL bGroups); +// Miscellaneous +BOOL CALLBACK SaveWindowEnumProc(HWND hWndGroup, LPARAM lParam); diff --git a/PROGMGR2/resource.h b/PROGMGR2/resource.h new file mode 100644 index 0000000..3811e32 --- /dev/null +++ b/PROGMGR2/resource.h @@ -0,0 +1,134 @@ +/* * * * * * * *\ + RESOURCE.H - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's resource collection. + ** NO DEPENDENCIES ** + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Pragmas */ +#ifndef RC_INVOKED +#pragma once +#endif + +/* Icon Library */ +// Primary, 1-9 +#define IDI_PROGMGR 1 +#define IDI_PROGGRP 2 +#define IDI_PROGITM 3 +#define IDI_COMMON 4 +#define IDI_PERSONAL 5 +// Secondary, 10-19 +// #define IDI_COMMS 10 +// #define IDI_CONSOLE 11 +// #define IDI_DOCUMENT 12 +// #define IDI_SPREADSHEET 13 +// Tertiary, 20+ +// #define IDI_SUPERMAN 20 + +/* Menus and Commands */ +// Context Menus and Accelerators +#define IDM_MAIN 100 +#define IDM_ITEM 101 +#define IDM_GROUP 102 +#define IDA_ACCELS 103 +// File, 110-119 +#define IDM_FILE 110 +#define IDM_FILE_NEW 111 +#define IDM_FILE_NEW_GROUP 112 +#define IDM_FILE_NEW_ITEM 113 +#define IDM_FILE_OPEN 114 +#define IDM_FILE_MOVE 115 +#define IDM_FILE_COPY 116 +#define IDM_FILE_DELETE 117 +#define IDM_FILE_PROPS 118 +#define IDM_FILE_RUN 119 +#define IDM_FILE_EXIT 120 +// Options, 130-149 +#define IDM_OPTIONS 130 +#define IDM_OPTIONS_AUTOARRANGE 131 +#define IDM_OPTIONS_MINONRUN 132 +#define IDM_OPTIONS_TOPMOST 133 +#define IDM_OPTIONS_SHOWUSERNAME 134 +#define IDM_OPTIONS_SAVESETTINGS 135 +#define IDM_OPTIONS_SAVENOW 136 +// Window, 150-169, 5000+ +#define IDM_WINDOW 150 +#define IDM_WINDOW_CASCADE 151 +#define IDM_WINDOW_TILE 152 +#define IDM_WINDOW_TILEHORIZONTALLY 153 +#define IDM_WINDOW_ARRANGEICONS 154 +#define IDM_WINDOW_CHILDSTART 5000 +// Help, 170-179 +#define IDM_HELP 170 +#define IDM_HELP_INDEX 171 +#define IDM_HELP_ABOUT 172 +// Miscellaneous, 180-199 +#define IDM_SHUTDOWN 180 +#define IDM_TASKMGR 181 +// Desktop Menus, 200-299 +#define IDM_DESK 200 +#define IDM_DESK_VIEW 201 +#define IDM_DESK_SORT 202 +#define IDM_DESK_SCREENRES 203 +#define IDM_DESK_PERSONALIZE 204 + +/* Dialogs */ +#define DLG_GROUP 1 +#define DLG_ITEM 2 +#define DLG_POWER 3 + +/* Dialog Controls */ +// Buttons +#define IDD_OK 1 +#define IDD_CANCEL 2 +#define IDD_BROWSE 3 +#define IDD_BROWSE2 4 +#define IDD_CHICON 5 +// Radio Buttons +#define IDD_WORKDIR 100 +#define IDD_COMMGROUP 101 +// Input Controls +#define IDD_NAME 200 +#define IDD_PATH 201 +#define IDD_WORKPATH 202 +#define IDD_HOTKEY 203 +// Static Controls +#define IDD_STAT_ICON 300 +#define IDD_STAT_WORKDIR 301 + +/* String Table */ +#define IDS_APPTITLE 1 +#define IDS_PMCLASS 2 +#define IDS_DTCLASS 3 +#define IDS_GRPCLASS 4 +#define IDS_WEBSITE 5 +// Menu Commands +#define IDS_RUN 100 +#define IDS_TASKMGR 101 +#define IDS_EXIT 102 +#define IDS_SHUTDOWN 103 +// General Dialog +#define IDS_DLG_OK 200 +#define IDS_DLG_CANCEL 201 +#define IDS_DLG_BROWSE 202 +// Icon Section +#define IDS_DLG_ICON 203 +#define IDS_DLG_CHICON 204 +// Properties Section +#define IDS_DLG_PROPS 205 +#define IDS_DLG_NAME 206 +#define IDS_DLG_DIRECTORY 207 +#define IDS_DLG_COMMGRP 208 +// Advanced Section +#define IDS_DLG_ADVANCED 209 +#define IDS_DLG_WORKDIR 210 +#define IDS_DLG_HOTKEY 211 +// Dialog Title +#define IDS_DLT_GRP_PROPS 300 +#define IDS_DLT_GRP_NEW 301 +#define IDS_DLT_ITEM_PROPS 302 +#define IDS_DLT_ITEM_NEW 303 +#define IDS_DLT_POWER 304 diff --git a/PROGMGR2/resource.rc b/PROGMGR2/resource.rc new file mode 100644 index 0000000..9090652 --- /dev/null +++ b/PROGMGR2/resource.rc @@ -0,0 +1,78 @@ +/* * * * * * * *\ + RESOURCE.RC - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + This file contains Program Manager's resources. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Necessary Evil */ +#define APSTUDIO_HIDDEN_SYMBOLS +#include +#include "resource.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +/* Language-based Resources */ +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(65001) // UTF-8 +#include "lang\res_en-US.rc" // English (US) +#include "lang\dlg_en-US.rc" // English (US) + +/* Icon Library */ +// Primary +#ifdef NDEBUG +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 +// Tertiary +// IDI_SUPERMAN ICON icons\misc\superman.ico + +/* Manifest */ +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "progmgr.exe.manifest" + +/* Version Information */ +#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 + FILEFLAGSMASK 0x3fL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", VER_FILEDESCRIPTION_STR "\0" + VALUE "FileVersion", VER_FILEVERSION_STR "\0" + VALUE "InternalName", VER_INTERNALNAME_STR "\0" + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR "\0" + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR "\0" + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 1033, 1200 + END +END diff --git a/PROGMGR2/sysint.c b/PROGMGR2/sysint.c new file mode 100644 index 0000000..090d8c1 --- /dev/null +++ b/PROGMGR2/sysint.c @@ -0,0 +1,88 @@ +/* * * * * * * *\ + SYSINT.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's system export functions. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#include +#include "progmgr.h" + +/* Functions */ + +/* * * *\ + RunFileDlg - + Produces a Run dialog window. + RETURNS - + True if successful, false if unsuccessful. +\* * * */ +BOOL RunFileDlg(HWND hWndOwner, + HICON hIcon, + LPWSTR lpszDir, + LPWSTR lpszTitle, + LPWSTR lpszDesc, + DWORD dwFlags) +{ + HMODULE hLib = LoadLibrary(TEXT("shell32.dll")); + + if (hLib) + { + FARPROC fLib = GetProcAddress(hLib, MAKEINTRESOURCEA(61)); + if (fLib(hWndOwner, hIcon, lpszDir, lpszTitle, lpszDesc, dwFlags)) + { + FreeLibrary(hLib); + return TRUE; + } + } + + return FALSE; +} + +/* * * *\ + ExitWindowsDialog - + Produces a Shutdown dialog window. + RETURNS - + True if successful, false if unsuccessful. +\* * * */ +BOOL ExitWindowsDialog(HWND hWndOwner) +{ + HMODULE hLib = LoadLibrary(TEXT("shell32.dll")); + + if (hLib) + { + FARPROC fLib = GetProcAddress(hLib, (LPCSTR)60); + if (fLib(hWndOwner)) + { + FreeLibrary(hLib); + return TRUE; + } + } + + return FALSE; +} + +/* * * *\ + SetShellWindow - + Sets a window as the shell window. + RETURNS - + True if successful, false if unsuccessful. +\* * * */ +BOOL SetShellWindow(HWND hWndShell) +{ + HMODULE hLib = GetModuleHandle(TEXT("user32.dll")); + + if (hLib) + { + FARPROC fLib = GetProcAddress(hLib, "SetShellWindow"); + if (fLib(hWndShell)) + { + return TRUE; + } + } + + return FALSE; +} diff --git a/PROGMGR2/version.inc b/PROGMGR2/version.inc new file mode 100644 index 0000000000000000000000000000000000000000..40b4bdbe6360f54f92e3cc3277eeccda13b459b8 GIT binary patch literal 1628 zcma)+ZBH6e5QWcIn)n}XwqIJ(BB}lX1d5voHOoqDLSn2%G%08R6Z_{|pP383;Ifd- zeZMp3oSC`%|KGl<3MFl*J$+C`1GSZ@uT($OQ;o5wCYE29=M`3Wy4PRLbgQv$wBYoU zuJoDlo9eVfW&>``I2&os-MPN7cf`)6ezOkhV$tGsrU^F}d=b9|ejkhs!6#kIP$IAO2pr+s?!*3);aGZZ%p^>n$DbMpkIS8$jTt&zve z#*v@A_E{rVkF?;*0<#;xWvVQaQRyF)n;z3KbPb#Hzwft#_pwgaW1PY&#&1HT7SFM- zD%yT@v}+=OJRGHRd$j}EgMY|d%rC`~N7ST<1bbE}GgxAiwy z?mu#B>5O{Kck*BUa>~)H3Ob$-({+lX7{g<*i!zhIs^~w{-147^EUfA`)yFDZZ~t^J vHMl;j^A@cglvZ7_*CJ)Bs;g56)(&`|+bZsDuC_DZjdPjTBIb$nUFZA+=HK26 literal 0 HcmV?d00001 diff --git a/PROGMGR2/wndproc.c b/PROGMGR2/wndproc.c new file mode 100644 index 0000000..6ffb155 --- /dev/null +++ b/PROGMGR2/wndproc.c @@ -0,0 +1,243 @@ +/* * * * * * * *\ + WNDPROC.C - + Copyright (c) 2024 Vortesys, Brady McDermott + DESCRIPTION - + Program Manager's window procedure. + LICENSE INFORMATION - + MIT License, see LICENSE.txt in the root folder +\* * * * * * * */ + +/* Headers */ +#define WIN32_LEAN_AND_MEAN +#define SECURITY_WIN32 +#include +#include +#include +#include +#include +#include +#include "progmgr.h" +#include "dialog.h" +#include "group.h" +#include "resource.h" +#include "registry.h" + +/* Functions */ + +/* * * *\ + WndProc - + Program Manager's window procedure. + RETURNS - + Zero if nothing, otherwise returns the good stuff. +\* * * */ +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + + case WM_CREATE: + { + // Play the logon sound. (But only if we're the default shell) + if (g_bIsDefaultShell) + PlaySound(TEXT("WindowsLogon"), NULL, SND_ALIAS | SND_ASYNC); + + return TRUE; + } + + case WM_SYSCOMMAND: + { + if ((wParam >= IDM_MAIN) && (wParam <= IDM_TASKMGR)) + { + if (wParam == IDM_TASKMGR) + { + ShellExecute(g_hWndProgMgr, TEXT("open"), TEXT("TASKMGR.EXE"), NULL, NULL, SW_NORMAL); + return 0; + } + + if (CmdProc(hWnd, wParam, lParam)) + return 0; + } + + return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam); + } + + case WM_COMMAND: + if (CmdProc(hWnd, wParam, lParam)) + return 0; + + return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam); + + case WM_CLOSE: + case WM_ENDSESSION: + if (bSaveSettings) + SaveConfig(TRUE, TRUE, TRUE, TRUE); + + if (g_bIsDefaultShell && (GetShellWindow() != NULL)) + SetShellWindow(0); + + PostQuitMessage(0); + break; + + default: + return DefFrameProc(hWnd, hWndMDIClient, message, wParam, lParam); + } + return 0; + +} + +/* * * *\ + CmdProc - + Program Manager's syscommand procedure. + RETURNS - + Zero if nothing, otherwise returns the good stuff. +\* * * */ +LRESULT CALLBACK CmdProc(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + + case IDM_SHUTDOWN: + DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_POWER), hWnd, (DLGPROC)ShutdownDlgProc); + break; + + case IDM_FILE_NEW_GROUP: + DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_GROUP), hWnd, (DLGPROC)NewGroupDlgProc); + break; + + case IDM_FILE_NEW_ITEM: + DialogBox(g_hAppInstance, MAKEINTRESOURCE(DLG_ITEM), hWnd, (DLGPROC)NewItemDlgProc); + break; + + case IDM_FILE_RUN: + RunFileDlg(hWnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY); + break; + + case IDM_FILE_EXIT: + PostQuitMessage(0); + break; + + case IDM_OPTIONS_AUTOARRANGE: + bAutoArrange = !bAutoArrange; + UpdateChecks(bAutoArrange, IDM_OPTIONS, IDM_OPTIONS_AUTOARRANGE); + goto SaveConfig; + + case IDM_OPTIONS_MINONRUN: + bMinOnRun = !bMinOnRun; + UpdateChecks(bMinOnRun, IDM_OPTIONS, IDM_OPTIONS_MINONRUN); + goto SaveConfig; + + case IDM_OPTIONS_TOPMOST: + bTopMost = !bTopMost; + 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; + + case IDM_OPTIONS_SHOWUSERNAME: + bShowUsername = !bShowUsername; + UpdateWindowTitle(); + UpdateChecks(bShowUsername, IDM_OPTIONS, IDM_OPTIONS_SHOWUSERNAME); + goto SaveConfig; + + case IDM_OPTIONS_SAVESETTINGS: + bSaveSettings = !bSaveSettings; + UpdateChecks(bSaveSettings, IDM_OPTIONS, IDM_OPTIONS_SAVESETTINGS); + goto SaveConfig; + + case IDM_OPTIONS_SAVENOW: + SaveConfig: + SaveConfig(TRUE, TRUE, TRUE, FALSE); + break; + + case IDM_WINDOW_CASCADE: + SendMessage(hWndMDIClient, WM_MDICASCADE, 0, 0); + break; + + case IDM_WINDOW_TILE: + SendMessage(hWndMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0); + break; + + case IDM_WINDOW_TILEHORIZONTALLY: + SendMessage(hWndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0); + break; + + case IDM_WINDOW_ARRANGEICONS: + SendMessage(hWndMDIClient, WM_MDIICONARRANGE, 0, 0); + break; + + case IDM_HELP_INDEX: + ShellExecute(NULL, TEXT("open"), g_szWebsite, NULL, NULL, SW_SHOWNORMAL); + break; + + case IDM_HELP_ABOUT: + { + WCHAR szTitle[40]; + + 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; + } + + return TRUE; +} + +/* * * *\ + UpdateChecks - + Updated checkmarks for a menu based on input + RETURNS - + Nothing! +\* * * */ +VOID UpdateChecks(BOOL bVarMenu, UINT uSubMenu, UINT uID) +{ + HMENU hMenu; + + hMenu = GetMenu(g_hWndProgMgr); + CheckMenuItem(hMenu, uID, (WORD)(bVarMenu ? MF_CHECKED : MF_UNCHECKED)); + + return; +} + +/* * * *\ + UpdateWindowTitle - + Updates Window title based on settings... and + current foreground group window if applicable? + RETURNS - + Nothing! +\* * * */ +VOID UpdateWindowTitle(VOID) +{ + WCHAR szUsername[UNLEN + 1] = TEXT(""); + DWORD dwUsernameLen = UNLEN; + 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(g_szAppTitle), g_szAppTitle); + + if (bShowUsername) + { + StringCchCat(szWindowTitle, ARRAYSIZE(szWindowTitle), TEXT(" - ")); + StringCchCat(szWindowTitle, ARRAYSIZE(szWindowTitle), szUsername); + } + + SetWindowText(g_hWndProgMgr, (LPCWSTR)&szWindowTitle); + + return; +}