rename dir 1
492
PROGMGR2/dialog.c
Normal file
@@ -0,0 +1,492 @@
|
||||
/* * * * * * * *\
|
||||
DIALOG.C -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Program Manager's dialogs and related
|
||||
common functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Headers */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <Commctrl.h>
|
||||
#include <Commdlg.h>
|
||||
#include <Shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <strsafe.h>
|
||||
#include "progmgr.h"
|
||||
#include "dialog.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
|
||||
/* Variables */
|
||||
WCHAR szDlgTitle[64];
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
NewGroupDlgProc -
|
||||
Dialog procedure for creating a group.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static GROUP grp = { 0 };
|
||||
BOOL bOKEnabled = FALSE;
|
||||
WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
HICON hIconDef = NULL;
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
// TODO:
|
||||
// Enable creation of common groups (enable the controls)
|
||||
// if permissions are available.
|
||||
// TODO:
|
||||
// fix minor GDI font/region leak
|
||||
|
||||
// Reset the necessary parts of the group structure
|
||||
grp.dwSignature = GRP_SIGNATURE;
|
||||
grp.wVersion = GRP_VERSION;
|
||||
grp.wChecksum = 0;
|
||||
grp.dwFlags = 0;
|
||||
grp.cItemArray = 0;
|
||||
// grp.pItemArray = 0; TODO: idk make sure this ain't all screwed up
|
||||
|
||||
// Set the window title
|
||||
LoadString(g_hAppInstance, IDS_DLT_GRP_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle));
|
||||
SetWindowText(hWndDlg, szDlgTitle);
|
||||
|
||||
// Populate the icon with the default path and index.
|
||||
GetModuleFileName(g_hAppInstance, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath));
|
||||
grp.iIconIndex = IDI_PROGGRP - 1;
|
||||
|
||||
// Get the default hIcon so we can delete it later
|
||||
hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0);
|
||||
|
||||
// Set the icon in the dialog
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
|
||||
// Set the maximum input length of the text boxes
|
||||
SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0);
|
||||
|
||||
// Disable the OK button since we're starting with no text in the box.
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
// Enable the common group checkbox if perms are good
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_COMMGROUP), g_bPermAdmin);
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if (LOWORD(wParam) == IDD_NAME)
|
||||
{
|
||||
// Name text control changed. See what's up...
|
||||
bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer));
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_CHICON:
|
||||
if (PickIconDlg(hWndDlg, (LPWSTR)&grp.szIconPath, ARRAYSIZE(grp.szIconPath), &grp.iIconIndex) == TRUE)
|
||||
{
|
||||
// Since we've got the new icon...
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&grp.szIconPath, grp.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_OK:
|
||||
// Check that all the applicable fields are filled out,
|
||||
// and if not then set the focus to the offending field
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_NAME));
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
if (bOKEnabled)
|
||||
{
|
||||
// Set the name of the group
|
||||
StringCchCopy(grp.szName, ARRAYSIZE(szBuffer), szBuffer);
|
||||
|
||||
// Set the flags of the group
|
||||
if (SendDlgItemMessage(hWndDlg, IDD_COMMGROUP, BM_GETCHECK, 0, 0) != BST_UNCHECKED)
|
||||
grp.dwFlags = grp.dwFlags || GRP_FLAG_COMMON;
|
||||
|
||||
// Set FILETIME
|
||||
GetSystemTimeAsFileTime(&grp.ftLastWrite);
|
||||
|
||||
// Set the rectangle of the group to be CW_USEDEFAULT
|
||||
grp.rcGroup.left = grp.rcGroup.top = grp.rcGroup.right = grp.rcGroup.bottom = CW_USEDEFAULT;
|
||||
|
||||
// Group's ready!
|
||||
if (CreateGroup(&grp) != NULL)
|
||||
{
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Failure!
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDef)
|
||||
DestroyIcon(hIconDef);
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
NewItemDlgProc -
|
||||
Dialog procedure for creating or modifying
|
||||
an item.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static ITEM itm = { 0 };
|
||||
BOOL bOKEnabled = FALSE;
|
||||
BOOL bWorkPath = FALSE;
|
||||
WCHAR szBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
WCHAR szPathBuffer[MAX_PATH] = { TEXT("\0") };
|
||||
HICON hIconDef = NULL;
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
// TODO:
|
||||
// require a valid group to be selected or else the dialog won't
|
||||
// EVEN BE AVAILABLE!!! or let you press ok.
|
||||
|
||||
// Reset the necessary parts of the item structure
|
||||
itm.dwFlags = 0;
|
||||
itm.uiHotkeyModifiers = 0;
|
||||
itm.uiHotkeyVirtualKey = 0;
|
||||
|
||||
// Set the window title
|
||||
LoadString(g_hAppInstance, IDS_DLT_ITEM_NEW, szDlgTitle, ARRAYSIZE(szDlgTitle));
|
||||
SetWindowText(hWndDlg, szDlgTitle);
|
||||
|
||||
// Populate the icon with the default path and index.
|
||||
GetModuleFileName(NULL, (LPWSTR)&itm.szIconPath, MAX_PATH);
|
||||
itm.iIconIndex = IDI_PROGITM - 1;
|
||||
|
||||
// Get the default hIcon so we can delete it later
|
||||
hIconDef = (HICON)SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_GETICON, 0, 0);
|
||||
|
||||
// Set the icon in the dialog
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)&itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
|
||||
// Set the maximum input length of the text boxes
|
||||
SendDlgItemMessage(hWndDlg, IDD_NAME, EM_LIMITTEXT, MAX_TITLE_LENGTH, 0);
|
||||
SendDlgItemMessage(hWndDlg, IDD_PATH, EM_LIMITTEXT, MAX_PATH, 0);
|
||||
SendDlgItemMessage(hWndDlg, IDD_WORKPATH, EM_LIMITTEXT, MAX_PATH, 0);
|
||||
|
||||
// Disable the OK button since we're starting with no text in the box.
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
if ((LOWORD(wParam) == IDD_NAME) || (LOWORD(wParam) == IDD_PATH) || (LOWORD(wParam) == IDD_WORKPATH))
|
||||
{
|
||||
// A control has changed. See what's up...
|
||||
bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer));
|
||||
bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
if (bWorkPath)
|
||||
bOKEnabled = bOKEnabled && GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
// Check that we have selected an MDI child window as well
|
||||
if ((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, FALSE) == (HWND)NULL)
|
||||
bOKEnabled = FALSE;
|
||||
|
||||
// Enable or disable the relevant controls based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_BROWSE:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
LPVOID lpData;
|
||||
DWORD dwVerBuffer = 0;
|
||||
UINT uiTitleLen = MAX_TITLE_LENGTH;
|
||||
WCHAR szNameBuffer[MAX_TITLE_LENGTH] = { TEXT("\0") };
|
||||
WCHAR szFileBuffer[MAX_PATH] = { TEXT("\0") };
|
||||
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer, ARRAYSIZE(szFileBuffer));
|
||||
|
||||
// Initialize the structure
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWndDlg;
|
||||
ofn.lpstrFilter = TEXT("Programs\0*.exe;*.bat;*.com;*.cmd;*.lnk\0All Files (*.*)\0*.*\0");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = (LPWSTR)&szFileBuffer;
|
||||
// ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = ARRAYSIZE(szFileBuffer);
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = NULL;
|
||||
ofn.Flags = OFN_FILEMUSTEXIST;
|
||||
|
||||
if (GetOpenFileName(&ofn) == TRUE)
|
||||
SetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szFileBuffer);
|
||||
else
|
||||
break;
|
||||
|
||||
// copy the filename to a new buffer for later
|
||||
StringCchCopy(szNameBuffer, ARRAYSIZE(szNameBuffer), szFileBuffer);
|
||||
|
||||
// let's retrieve the application's friendly name too
|
||||
dwVerBuffer = GetFileVersionInfoSize((LPCWSTR)szFileBuffer, NULL);
|
||||
// if (dwVerBuffer != 0)
|
||||
if (NULL)
|
||||
{
|
||||
lpData = malloc(dwVerBuffer);
|
||||
// TODO: totally redo this it doesn't work
|
||||
|
||||
if (lpData != NULL)
|
||||
GetFileVersionInfo((LPCWSTR)szFileBuffer, (DWORD)0, dwVerBuffer, lpData);
|
||||
else
|
||||
break;
|
||||
|
||||
// TODO: this is hardcoded to english. make it dynamic later
|
||||
// TODO: this is so busted lol, really make it dynamic so it works
|
||||
VerQueryValue(lpData,
|
||||
TEXT("\\StringFileInfo\\040904b0\\FileDescription"),
|
||||
(LPVOID)&szNameBuffer, &uiTitleLen); // == 0
|
||||
|
||||
if (lpData)
|
||||
free(lpData);
|
||||
}
|
||||
else
|
||||
{
|
||||
PathStripPath((LPWSTR)&szNameBuffer);
|
||||
PathRemoveExtension((LPWSTR)&szNameBuffer);
|
||||
}
|
||||
|
||||
SetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)szNameBuffer);
|
||||
|
||||
// let's get the icon now
|
||||
if (ExtractIcon(g_hAppInstance, (LPWSTR)szFileBuffer, -1) > 0)
|
||||
{
|
||||
// file contains at least one icon, set the itm struct values
|
||||
StringCchCopy(itm.szIconPath, ARRAYSIZE(itm.szIconPath), szFileBuffer);
|
||||
itm.iIconIndex = 0;
|
||||
|
||||
// update icon
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IDD_BROWSE2:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
||||
GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
|
||||
// Initialize the structure
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWndDlg;
|
||||
ofn.lpstrFilter = TEXT("Folders\0");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = (LPWSTR)&szPathBuffer;
|
||||
// ofn.lpstrFile[0] = '\0';
|
||||
ofn.nMaxFile = ARRAYSIZE(szPathBuffer);
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = NULL;
|
||||
ofn.Flags = OFN_FILEMUSTEXIST;
|
||||
|
||||
if (GetOpenFileName(&ofn) == TRUE) {
|
||||
SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case IDD_CHICON:
|
||||
if (PickIconDlg(hWndDlg, (LPWSTR)&itm.szIconPath, ARRAYSIZE(itm.szIconPath), &itm.iIconIndex) == TRUE)
|
||||
{
|
||||
// Since we've got the new icon...
|
||||
hIconDlg = ExtractIcon(g_hAppInstance, (LPWSTR)itm.szIconPath, itm.iIconIndex);
|
||||
SendDlgItemMessage(hWndDlg, IDD_STAT_ICON, STM_SETICON, (WPARAM)hIconDlg, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_WORKDIR:
|
||||
bWorkPath = IsDlgButtonChecked(hWndDlg, IDD_WORKDIR);
|
||||
|
||||
if (bWorkPath)
|
||||
{
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
PathRemoveFileSpec((LPWSTR)&szPathBuffer);
|
||||
SetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowText(GetDlgItem(hWndDlg, IDD_WORKPATH), 0);
|
||||
}
|
||||
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_STAT_WORKDIR), bWorkPath);
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_WORKPATH), bWorkPath);
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_BROWSE2), bWorkPath);
|
||||
|
||||
break;
|
||||
|
||||
case IDD_OK:
|
||||
// Check that all the applicable fields are filled out,
|
||||
// and if not then set the focus to the offending field
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_NAME, (LPWSTR)&szBuffer, ARRAYSIZE(szBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_NAME));
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_PATH));
|
||||
if (bWorkPath)
|
||||
{
|
||||
if (!(bOKEnabled = GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer))))
|
||||
SetFocus(GetDlgItem(hWndDlg, IDD_WORKPATH));
|
||||
}
|
||||
|
||||
// Enable or disable the OK button based on the information
|
||||
EnableWindow(GetDlgItem(hWndDlg, IDD_OK), bOKEnabled);
|
||||
|
||||
if (bOKEnabled)
|
||||
{
|
||||
// Set the name of the item
|
||||
StringCchCopy(itm.szName, ARRAYSIZE(szBuffer), szBuffer);
|
||||
|
||||
// And the paths...
|
||||
GetDlgItemText(hWndDlg, IDD_PATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
StringCchCopy(itm.szExecPath, ARRAYSIZE(szPathBuffer), szPathBuffer);
|
||||
GetDlgItemText(hWndDlg, IDD_WORKPATH, (LPWSTR)&szPathBuffer, ARRAYSIZE(szPathBuffer));
|
||||
StringCchCopy(itm.szWorkPath, ARRAYSIZE(szPathBuffer), szPathBuffer);
|
||||
|
||||
// Item's ready!
|
||||
if (CreateItem((HWND)SendMessage(hWndMDIClient, WM_MDIGETACTIVE, 0, 0), &itm) != NULL)
|
||||
{
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Failure!
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDef)
|
||||
DestroyIcon(hIconDef);
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* * * *\
|
||||
ShutdownDlgProc -
|
||||
Dialog procedure for powering off the computer.
|
||||
RETURNS -
|
||||
TRUE if message is handled, FALSE otherwise.
|
||||
\* * * */
|
||||
BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HICON hIconDlg = NULL;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
|
||||
case WM_INITDIALOG:
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
||||
{
|
||||
|
||||
case IDD_OK:
|
||||
{
|
||||
}
|
||||
|
||||
case IDD_CANCEL:
|
||||
EndDialog(hWndDlg, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Cleanup
|
||||
if (hIconDlg)
|
||||
DestroyIcon(hIconDlg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
17
PROGMGR2/dialog.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* * * * * * * *\
|
||||
DIALOG.H -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Dialog function prototypes and related
|
||||
common dialog functions.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Function Prototypes */
|
||||
BOOL CALLBACK NewGroupDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK NewItemDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
BOOL CALLBACK ShutdownDlgProc(HWND hWndDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
677
PROGMGR2/group.c
Normal file
@@ -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 <Windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <uxtheme.h>
|
||||
#include "progmgr.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
|
||||
/* 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;
|
||||
}
|
||||
92
PROGMGR2/group.h
Normal file
@@ -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);
|
||||
38
PROGMGR2/grpupdat.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* * * * * * * *\
|
||||
GRPUPDAT.H -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
DESCRIPTION -
|
||||
Header containing classic program group structures
|
||||
in order to facilitate conversion to the new format.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Pragmas */
|
||||
#pragma once
|
||||
|
||||
/* Includes */
|
||||
#include <wtypes.h>
|
||||
|
||||
/* Definitions */
|
||||
// Group signatures
|
||||
#define OLDGRP_SIGNATURE 0x43554D50L // PMUC
|
||||
|
||||
/* Structures */
|
||||
// Old group format, .GRP
|
||||
typedef struct _OLDGROUP {
|
||||
DWORD dwMagic; // Set to OLDGRP_SIGNATURE
|
||||
WORD wCheckSum; // Seemingly unused
|
||||
WORD cbGroup; // Size of group
|
||||
RECT rcNormal; // Window rect
|
||||
POINT ptMin; // Minimized window position
|
||||
WORD nCmdShow; // Min/max state
|
||||
WORD pName; // Group name
|
||||
WORD cxIcon; // Icon width
|
||||
WORD cyIcon; // Icon height
|
||||
WORD wIconFormat;
|
||||
WORD wReserved; // Unused
|
||||
|
||||
WORD cItems; // Number of items
|
||||
WORD rgiItems[1]; // Array of item offsets
|
||||
} OLDGROUP, * POLDGROUP;
|
||||
BIN
PROGMGR2/icons/common.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/bkgsrc.pdn
Normal file
BIN
PROGMGR2/icons/misc/bkgsrctxt.pdn
Normal file
BIN
PROGMGR2/icons/misc/comms.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/console.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/console.pdn
Normal file
BIN
PROGMGR2/icons/misc/data.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/document.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/msdos.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/pmcomm.pdn
Normal file
BIN
PROGMGR2/icons/misc/pmdata.pdn
Normal file
BIN
PROGMGR2/icons/misc/pmlogo.pdn
Normal file
BIN
PROGMGR2/icons/misc/pmsheet.pdn
Normal file
BIN
PROGMGR2/icons/misc/pmword.pdn
Normal file
BIN
PROGMGR2/icons/misc/spsheet.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/superman.ico
Normal file
|
After Width: | Height: | Size: 766 B |
BIN
PROGMGR2/icons/misc/wfdir.pdn
Normal file
BIN
PROGMGR2/icons/misc/wftrdir.pdn
Normal file
BIN
PROGMGR2/icons/misc/wftree.pdn
Normal file
BIN
PROGMGR2/icons/misc/winoldap.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/misc/winoldap.pdn
Normal file
BIN
PROGMGR2/icons/personal.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/pmgroup.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/pmitem.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
PROGMGR2/icons/progmgr.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
PROGMGR2/icons/progmgrd.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
PROGMGR2/icons/src/common.pdn
Normal file
BIN
PROGMGR2/icons/src/personal.pdn
Normal file
BIN
PROGMGR2/icons/src/pmgroup.pdn
Normal file
BIN
PROGMGR2/icons/src/pmitem.pdn
Normal file
BIN
PROGMGR2/icons/src/progmgr.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
PROGMGR2/icons/src/progmgr.pdn
Normal file
BIN
PROGMGR2/icons/src/progmgrd.ico
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
PROGMGR2/icons/src/progmgrd.pdn
Normal file
93
PROGMGR2/lang/dlg_en-US.rc
Normal file
@@ -0,0 +1,93 @@
|
||||
/* * * * * * * *\
|
||||
DLG_EN-US.RC -
|
||||
Copyright (c) 2024 Vortesys, Brady McDermott
|
||||
LANGUAGE -
|
||||
English, US
|
||||
CREDITS -
|
||||
freedom7341
|
||||
DESCRIPTION -
|
||||
This file contains the language-specific dialogs
|
||||
for Program Manager.
|
||||
LICENSE INFORMATION -
|
||||
MIT License, see LICENSE.txt in the root folder
|
||||
\* * * * * * * */
|
||||
|
||||
/* Necessary Evil */
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include <windows.h>
|
||||
#define STRICT
|
||||
#include <CommCtrl.h>
|
||||
#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
|
||||
}
|
||||
160
PROGMGR2/lang/res_en-US.rc
Normal file
@@ -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 <windows.h>
|
||||
#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
|
||||
}
|
||||
221
PROGMGR2/progmgr.c
Normal file
@@ -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 <Windows.h>
|
||||
#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
|
||||
|
||||
*/
|
||||
28
PROGMGR2/progmgr.exe.manifest
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 and Windows 11 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
61
PROGMGR2/progmgr.h
Normal file
@@ -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);
|
||||
201
PROGMGR2/progmgr.vcxproj
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{b76b940d-b61a-456e-8569-72f64cf91afb}</ProjectGuid>
|
||||
<RootNamespace>progmgr</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
|
||||
<ManifestFile>$(IntDir)$(TargetName)$(TargetExt).manifest</ManifestFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="dialog.h" />
|
||||
<ClInclude Include="group.h" />
|
||||
<ClInclude Include="grpupdat.h" />
|
||||
<ClInclude Include="progmgr.h" />
|
||||
<ClInclude Include="registry.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dialog.c" />
|
||||
<ClCompile Include="progmgr.c" />
|
||||
<ClCompile Include="registry.c" />
|
||||
<ClCompile Include="group.c" />
|
||||
<ClCompile Include="sysint.c" />
|
||||
<ClCompile Include="wndproc.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="lang\dlg_en-US.rc" />
|
||||
<ResourceCompile Include="lang\res_en-US.rc" />
|
||||
<ResourceCompile Include="resource.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="version.inc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="progmgr.exe.manifest" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
84
PROGMGR2/progmgr.vcxproj.filters
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Language Resources">
|
||||
<UniqueIdentifier>{71dbbd6d-c82a-4fac-a0ff-74be88190f82}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files\en-US">
|
||||
<UniqueIdentifier>{2a11d118-5a5c-4681-86dc-31de4f0251ff}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="progmgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="registry.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="group.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="grpupdat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dialog.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="progmgr.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="registry.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sysint.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wndproc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="group.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dialog.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resource.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="lang\res_en-US.rc">
|
||||
<Filter>Resource Files\en-US</Filter>
|
||||
</ResourceCompile>
|
||||
<ResourceCompile Include="lang\dlg_en-US.rc">
|
||||
<Filter>Resource Files\en-US</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="version.inc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="progmgr.exe.manifest">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Manifest>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
388
PROGMGR2/registry.c
Normal file
@@ -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 <Windows.h>
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#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;
|
||||
}
|
||||
55
PROGMGR2/registry.h
Normal file
@@ -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);
|
||||
134
PROGMGR2/resource.h
Normal file
@@ -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
|
||||
78
PROGMGR2/resource.rc
Normal file
@@ -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 <windows.h>
|
||||
#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
|
||||
88
PROGMGR2/sysint.c
Normal file
@@ -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 <Windows.h>
|
||||
#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;
|
||||
}
|
||||
BIN
PROGMGR2/version.inc
Normal file
243
PROGMGR2/wndproc.c
Normal file
@@ -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 <Windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <shellapi.h>
|
||||
#include <Lmcons.h>
|
||||
#include <security.h>
|
||||
#include <Mmsystem.h>
|
||||
#include "progmgr.h"
|
||||
#include "dialog.h"
|
||||
#include "group.h"
|
||||
#include "resource.h"
|
||||
#include "registry.h"
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* * * *\
|
||||
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;
|
||||
}
|
||||