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