2016-03-04 19:22:35 +00:00
/*
* Program Manager
*
* Copyright 1996 Ulrich Schmid
* Copyright 2002 Sylvain Petreolle
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
2016-05-11 22:21:53 +00:00
/*
* PROJECT : ReactOS Program Manager
* COPYRIGHT : GPL - See COPYING in the top level directory
* FILE : base / shell / progman / main . c
* PURPOSE : ProgMan entry point & MDI window
* PROGRAMMERS : Ulrich Schmid
* Sylvain Petreolle
* Hermes Belusca - Maito ( hermes . belusca @ sfr . fr )
*/
2016-03-04 19:22:35 +00:00
# include "progman.h"
2016-03-05 08:45:08 +00:00
# include <shellapi.h>
2016-05-11 22:21:53 +00:00
# define WC_MDICLIENTA "MDICLIENT"
# define WC_MDICLIENTW L"MDICLIENT"
# ifdef UNICODE
# define WC_MDICLIENT WC_MDICLIENTW
# else
# define WC_MDICLIENT WC_MDICLIENTA
# endif
2016-03-04 19:22:35 +00:00
GLOBALS Globals ;
2016-05-11 22:21:53 +00:00
static VOID MAIN_LoadGroups ( VOID ) ;
2016-03-04 19:22:35 +00:00
static VOID MAIN_MenuCommand ( HWND hWnd , WPARAM wParam , LPARAM lParam ) ;
2016-05-11 22:21:53 +00:00
static ATOM MAIN_RegisterMainWinClass ( VOID ) ;
static VOID MAIN_CreateMainWindow ( VOID ) ;
static VOID MAIN_CreateMDIWindow ( VOID ) ;
static VOID MAIN_AutoStart ( VOID ) ;
# define BUFFER_SIZE 1024
/*
* Memory management functions
*/
PVOID
Alloc ( IN DWORD dwFlags ,
IN SIZE_T dwBytes )
{
return HeapAlloc ( GetProcessHeap ( ) , dwFlags , dwBytes ) ;
}
BOOL
Free ( IN PVOID lpMem )
{
return HeapFree ( GetProcessHeap ( ) , 0 , lpMem ) ;
}
PVOID
ReAlloc ( IN DWORD dwFlags ,
IN PVOID lpMem ,
IN SIZE_T dwBytes )
{
return HeapReAlloc ( GetProcessHeap ( ) , dwFlags , lpMem , dwBytes ) ;
}
PVOID
AppendToBuffer ( IN PVOID pBuffer ,
IN PSIZE_T pdwBufferSize ,
IN PVOID pData ,
IN SIZE_T dwDataSize )
{
PVOID pTmp ;
SIZE_T dwBufferSize ;
dwBufferSize = dwDataSize + * pdwBufferSize ;
if ( pBuffer )
pTmp = ReAlloc ( 0 , pBuffer , dwBufferSize ) ;
else
pTmp = Alloc ( 0 , dwBufferSize ) ;
if ( ! pTmp )
return NULL ;
memcpy ( ( PVOID ) ( ( ULONG_PTR ) pTmp + * pdwBufferSize ) , pData , dwDataSize ) ;
* pdwBufferSize = dwBufferSize ;
return pTmp ;
}
/*
* Debugging helpers
*/
VOID
PrintStringV ( IN LPCWSTR szStr ,
IN va_list args )
{
WCHAR Buffer [ 4096 ] ;
_vsnwprintf ( Buffer , ARRAYSIZE ( Buffer ) , szStr , args ) ;
MessageBoxW ( Globals . hMainWnd , Buffer , L " Information " , MB_OK ) ;
}
VOID
PrintString ( IN LPCWSTR szStr , . . . )
{
va_list args ;
va_start ( args , szStr ) ;
PrintStringV ( szStr , args ) ;
va_end ( args ) ;
}
VOID
PrintResourceString ( IN UINT uID , . . . )
{
WCHAR Buffer [ 4096 ] ;
va_list args ;
va_start ( args , uID ) ;
LoadStringW ( Globals . hInstance , uID , Buffer , ARRAYSIZE ( Buffer ) ) ;
PrintStringV ( Buffer , args ) ;
va_end ( args ) ;
}
VOID
PrintWin32Error ( IN LPWSTR Message , IN DWORD ErrorCode )
{
LPWSTR lpMsgBuf ;
FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
NULL , ErrorCode , MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) ,
( LPWSTR ) & lpMsgBuf , 0 , NULL ) ;
PrintString ( L " %s: %s \n " , Message , lpMsgBuf ) ;
LocalFree ( lpMsgBuf ) ;
}
int ShowLastWin32Error ( VOID )
{
DWORD dwError ;
LPWSTR lpMsgBuf = NULL ;
WCHAR Buffer [ 4096 ] ;
dwError = GetLastError ( ) ;
FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
NULL , dwError , MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) ,
( LPWSTR ) & lpMsgBuf , 0 , NULL ) ;
_snwprintf ( Buffer , ARRAYSIZE ( Buffer ) , L " Error %d: %s \n " , dwError , lpMsgBuf ) ;
LocalFree ( lpMsgBuf ) ;
return MessageBoxW ( Globals . hMainWnd , Buffer , L " Error " , MB_OK ) ;
}
/* Copied and adapted from dll/win32/userenv/environment.c!GetUserAndDomainName */
static
BOOL
GetUserAndDomainName ( OUT LPWSTR * UserName ,
OUT LPWSTR * DomainName )
{
BOOL bRet = TRUE ;
HANDLE hToken ;
DWORD cbTokenBuffer = 0 ;
PTOKEN_USER pUserToken ;
LPWSTR lpUserName = NULL ;
LPWSTR lpDomainName = NULL ;
DWORD cbUserName = 0 ;
DWORD cbDomainName = 0 ;
SID_NAME_USE SidNameUse ;
/* Get the process token */
if ( ! OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & hToken ) )
return FALSE ;
/* Retrieve token's information */
if ( ! GetTokenInformation ( hToken , TokenUser , NULL , 0 , & cbTokenBuffer ) )
{
if ( GetLastError ( ) ! = ERROR_INSUFFICIENT_BUFFER )
{
CloseHandle ( hToken ) ;
return FALSE ;
}
}
pUserToken = Alloc ( HEAP_ZERO_MEMORY , cbTokenBuffer ) ;
if ( ! pUserToken )
{
CloseHandle ( hToken ) ;
return FALSE ;
}
if ( ! GetTokenInformation ( hToken , TokenUser , pUserToken , cbTokenBuffer , & cbTokenBuffer ) )
{
Free ( pUserToken ) ;
CloseHandle ( hToken ) ;
return FALSE ;
}
CloseHandle ( hToken ) ;
/* Retrieve the domain and user name */
if ( ! LookupAccountSidW ( NULL ,
pUserToken - > User . Sid ,
NULL ,
& cbUserName ,
NULL ,
& cbDomainName ,
& SidNameUse ) )
{
if ( GetLastError ( ) ! = ERROR_INSUFFICIENT_BUFFER )
{
bRet = FALSE ;
goto done ;
}
}
lpUserName = Alloc ( HEAP_ZERO_MEMORY , cbUserName * sizeof ( WCHAR ) ) ;
if ( lpUserName = = NULL )
{
bRet = FALSE ;
goto done ;
}
lpDomainName = Alloc ( HEAP_ZERO_MEMORY , cbDomainName * sizeof ( WCHAR ) ) ;
if ( lpDomainName = = NULL )
{
bRet = FALSE ;
goto done ;
}
if ( ! LookupAccountSidW ( NULL ,
pUserToken - > User . Sid ,
lpUserName ,
& cbUserName ,
lpDomainName ,
& cbDomainName ,
& SidNameUse ) )
{
bRet = FALSE ;
goto done ;
}
* UserName = lpUserName ;
* DomainName = lpDomainName ;
done :
if ( bRet = = FALSE )
{
if ( lpUserName ! = NULL )
Free ( lpUserName ) ;
if ( lpDomainName ! = NULL )
Free ( lpDomainName ) ;
}
Free ( pUserToken ) ;
return bRet ;
}
static
VOID
MAIN_SetMainWindowTitle ( VOID )
{
LPWSTR caption ;
SIZE_T size ;
LPWSTR lpDomainName = NULL ;
LPWSTR lpUserName = NULL ;
if ( GetUserAndDomainName ( & lpUserName , & lpDomainName ) & & lpUserName & & lpDomainName )
{
size = ( 256 + 3 + wcslen ( lpDomainName ) + wcslen ( lpUserName ) + 1 ) * sizeof ( WCHAR ) ;
caption = Alloc ( HEAP_ZERO_MEMORY , size ) ;
if ( caption )
{
2016-10-27 10:21:13 +00:00
StringCbPrintfW ( caption , size , L " %s - %s \\ %s " , szTitle , lpDomainName , lpUserName ) ;
2016-05-11 22:21:53 +00:00
SetWindowTextW ( Globals . hMainWnd , caption ) ;
Free ( caption ) ;
}
else
{
SetWindowTextW ( Globals . hMainWnd , szTitle ) ;
}
}
else
{
SetWindowTextW ( Globals . hMainWnd , szTitle ) ;
}
if ( lpUserName ) Free ( lpUserName ) ;
if ( lpDomainName ) Free ( lpDomainName ) ;
}
static
BOOL
MAIN_LoadSettings ( VOID )
{
LPWSTR lpszTmp ;
LPWSTR lpszSection ;
LONG lRet ;
WCHAR dummy [ 2 ] ;
LPWSTR lpszKeyValue ;
const LPCWSTR lpszIniFile = L " progman.ini " ;
WCHAR szWinDir [ MAX_PATH ] ;
LPWSTR lpszKey ;
DWORD Value ;
HKEY hKey ;
BOOL bIsIniMigrated ;
DWORD dwSize ;
LPWSTR lpszSections ;
LPWSTR lpszData ;
DWORD dwRet ;
DWORD dwType ;
LPWSTR lpszValue ;
bIsIniMigrated = FALSE ;
lpszSections = NULL ;
lpszData = NULL ;
/* Try to create/open the Program Manager user key */
if ( RegCreateKeyExW ( HKEY_CURRENT_USER ,
L " SOFTWARE \\ Microsoft \\ Windows NT \\ CurrentVersion \\ Program Manager " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyProgMan ,
NULL ) ! = ERROR_SUCCESS )
{
return FALSE ;
}
/*
* TODO : Add the explanation for the migration . . .
*/
dwSize = sizeof ( Value ) ;
lRet = RegQueryValueExW ( Globals . hKeyProgMan , L " IniMigrated " , NULL , & dwType , ( LPBYTE ) & Value , & dwSize ) ;
if ( lRet ! = ERROR_SUCCESS | | dwType ! = REG_DWORD )
Value = 0 ;
bIsIniMigrated = ! ! Value ;
if ( bIsIniMigrated )
{
/* The migration was already done, just load the settings */
goto LoadSettings ;
}
/* Perform the migration */
bIsIniMigrated = TRUE ;
dwSize = ARRAYSIZE ( dummy ) ;
SetLastError ( 0 ) ;
GetPrivateProfileSectionW ( L " Settings " , dummy , dwSize , lpszIniFile ) ;
if ( GetLastError ( ) = = ERROR_FILE_NOT_FOUND )
goto MigrationDone ;
SetLastError ( 0 ) ;
GetPrivateProfileSectionW ( L " Groups " , dummy , dwSize , lpszIniFile ) ;
if ( GetLastError ( ) = = ERROR_FILE_NOT_FOUND )
goto MigrationDone ;
GetWindowsDirectoryW ( szWinDir , ARRAYSIZE ( szWinDir ) ) ;
// NOTE: GCC complains we cannot use the "\u2022" (UNICODE Code Point) notation for specifying the bullet character,
// because it's only available in C++ or in C99. On the contrary MSVC is fine with it.
// Instead we use a hex specification for the character: "\x2022".
// Note also that the character "\x07" gives also a bullet, but a larger one.
PrintString (
L " The Program Manager has detected the presence of a legacy settings file PROGMAN.INI in the directory '%s' "
L " and is going to migrate its contents into the current-user Program Manager settings registry key: \n "
L " HKCU \\ SOFTWARE \\ Microsoft \\ Windows NT \\ CurrentVersion \\ Program Manager "
L " \n \n "
L " \x2022 The migration operation will potentially overwrite all the existing current-user Program Manager settings in the registry by those stored in the PROGMAN.INI file. \n "
L " \n "
L " \x2022 The migration is done once, so that, at the next launch of the Program Manager, the new migrated settings are directly used. \n "
L " \n "
L " \x2022 It is possible to trigger later the migration by manually deleting the registry value \" IniMigrated \" under the current-user Program Manager settings registry key (specified above). \n "
L " \n "
L " Would you like to migrate its contents into the registry? " ,
szWinDir ) ;
for ( dwSize = BUFFER_SIZE ; ; dwSize + = BUFFER_SIZE )
{
lpszSections = Alloc ( 0 , dwSize * sizeof ( WCHAR ) ) ;
dwRet = GetPrivateProfileSectionNamesW ( lpszSections , dwSize , lpszIniFile ) ;
if ( dwRet < dwSize - 2 )
break ;
Free ( lpszSections ) ;
}
lpszSection = lpszSections ;
while ( * lpszSection )
{
lRet = RegCreateKeyExW ( Globals . hKeyProgMan ,
lpszSection ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_WRITE ,
NULL ,
& hKey ,
NULL ) ;
if ( lRet = = ERROR_SUCCESS )
{
for ( dwSize = BUFFER_SIZE ; ; dwSize + = BUFFER_SIZE )
{
lpszData = Alloc ( 0 , dwSize * sizeof ( WCHAR ) ) ;
dwRet = GetPrivateProfileSectionW ( lpszSection , lpszData , dwSize , lpszIniFile ) ;
if ( dwRet < dwSize - 2 )
break ;
Free ( lpszData ) ;
}
lpszKeyValue = lpszData ;
while ( * lpszKeyValue )
{
lpszKey = lpszKeyValue ;
lpszValue = wcschr ( lpszKeyValue , L ' = ' ) ;
lpszKeyValue + = ( wcslen ( lpszKeyValue ) + 1 ) ;
if ( lpszValue )
{
* lpszValue = ' \0 ' ;
+ + lpszValue ;
Value = wcstoul ( lpszValue , & lpszTmp , 0 ) ;
if ( lpszTmp - lpszValue > = wcslen ( lpszValue ) )
{
lpszValue = ( LPWSTR ) & Value ;
dwSize = sizeof ( Value ) ;
dwType = REG_DWORD ;
}
else
{
dwSize = wcslen ( lpszValue ) * sizeof ( WCHAR ) ;
dwType = REG_SZ ;
}
}
else
{
dwSize = 0 ;
dwType = REG_DWORD ;
}
lRet = RegSetValueExW ( hKey , lpszKey , 0 , dwType , ( LPBYTE ) lpszValue , dwSize ) ;
}
Free ( lpszData ) ;
RegCloseKey ( hKey ) ;
lpszSection + = ( wcslen ( lpszSection ) + 1 ) ;
}
}
Free ( lpszSections ) ;
MigrationDone :
Value = TRUE ;
RegSetValueExW ( Globals . hKeyProgMan , L " IniMigrated " , 0 , REG_DWORD , ( LPBYTE ) & Value , sizeof ( Value ) ) ;
LoadSettings :
/* Create the necessary registry keys for the Program Manager and load its settings from the registry */
lRet = RegCreateKeyExW ( Globals . hKeyProgMan ,
L " Settings " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyPMSettings ,
NULL ) ;
lRet = RegCreateKeyExW ( Globals . hKeyProgMan ,
L " Common Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyPMCommonGroups ,
NULL ) ;
lRet = RegCreateKeyExW ( Globals . hKeyProgMan ,
L " Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyPMAnsiGroups ,
NULL ) ;
lRet = RegCreateKeyExW ( Globals . hKeyProgMan ,
L " UNICODE Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyPMUnicodeGroups ,
NULL ) ;
lRet = RegCreateKeyExW ( HKEY_CURRENT_USER ,
L " Program Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyAnsiGroups ,
NULL ) ;
lRet = RegCreateKeyExW ( HKEY_CURRENT_USER ,
L " UNICODE Program Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyUnicodeGroups ,
NULL ) ;
lRet = RegCreateKeyExW ( HKEY_LOCAL_MACHINE ,
L " SOFTWARE \\ Program Groups " ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& Globals . hKeyCommonGroups ,
NULL ) ;
dwSize = sizeof ( Globals . bAutoArrange ) ;
RegQueryValueExW ( Globals . hKeyPMSettings , L " AutoArrange " , NULL , & dwType , ( LPBYTE ) & Globals . bAutoArrange , & dwSize ) ;
dwSize = sizeof ( Globals . bMinOnRun ) ;
RegQueryValueExW ( Globals . hKeyPMSettings , L " MinOnRun " , NULL , & dwType , ( LPBYTE ) & Globals . bMinOnRun , & dwSize ) ;
dwSize = sizeof ( Globals . bSaveSettings ) ;
RegQueryValueExW ( Globals . hKeyPMSettings , L " SaveSettings " , NULL , & dwType , ( LPBYTE ) & Globals . bSaveSettings , & dwSize ) ;
return TRUE ;
}
static
BOOL
MAIN_SaveSettings ( VOID )
{
WINDOWPLACEMENT WndPl ;
DWORD dwSize ;
WCHAR buffer [ 100 ] ;
WndPl . length = sizeof ( WndPl ) ;
GetWindowPlacement ( Globals . hMainWnd , & WndPl ) ;
2016-10-27 10:21:13 +00:00
StringCbPrintfW ( buffer , sizeof ( buffer ) ,
L " %d %d %d %d %d " ,
WndPl . rcNormalPosition . left ,
WndPl . rcNormalPosition . top ,
WndPl . rcNormalPosition . right ,
WndPl . rcNormalPosition . bottom ,
WndPl . showCmd ) ;
2016-05-11 22:21:53 +00:00
dwSize = wcslen ( buffer ) * sizeof ( WCHAR ) ;
RegSetValueExW ( Globals . hKeyPMSettings , L " Window " , 0 , REG_SZ , ( LPBYTE ) buffer , dwSize ) ;
return TRUE ;
}
2016-03-04 19:22:35 +00:00
/***********************************************************************
*
* WinMain
*/
2016-05-11 22:21:53 +00:00
INT WINAPI wWinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPWSTR lpCmdLine , INT nCmdShow )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
MSG msg ;
INITCOMMONCONTROLSEX icex ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/*
* Set our shutdown parameters : we want to shutdown the very last ,
* but before any TaskMgr instance ( which has a shutdown level of 1 ) .
*/
SetProcessShutdownParameters ( 2 , 0 ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
Globals . hInstance = hInstance ;
Globals . hGroups = NULL ;
Globals . hActiveGroup = NULL ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Load Program Manager's settings */
MAIN_LoadSettings ( ) ;
/* Load the default icons */
2016-05-12 19:54:53 +00:00
Globals . hDefaultIcon = LoadIconW ( NULL , MAKEINTRESOURCEW ( IDI_WINLOGO ) ) ;
Globals . hMainIcon = LoadIconW ( Globals . hInstance , MAKEINTRESOURCEW ( IDI_APPICON ) ) ;
2016-05-11 22:21:53 +00:00
Globals . hPersonalGroupIcon = LoadIconW ( Globals . hInstance , MAKEINTRESOURCEW ( IDI_GROUP_PERSONAL_ICON ) ) ;
Globals . hCommonGroupIcon = LoadIconW ( Globals . hInstance , MAKEINTRESOURCEW ( IDI_GROUP_COMMON_ICON ) ) ;
/* Initialize the common controls */
icex . dwSize = sizeof ( icex ) ;
icex . dwICC = ICC_HOTKEY_CLASS | ICC_LISTVIEW_CLASSES ; // | ICC_STANDARD_CLASSES;
InitCommonControlsEx ( & icex ) ;
/* Register the window classes */
if ( ! hPrevInstance ) // FIXME: Unused on Win32!
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
if ( ! MAIN_RegisterMainWinClass ( ) ) goto Quit ;
if ( ! GROUP_RegisterGroupWinClass ( ) ) goto Quit ;
2016-03-04 19:22:35 +00:00
}
2016-05-11 22:21:53 +00:00
/* Set up the strings, the main window, the accelerators, the menu, and the MDI child window */
STRING_LoadStrings ( ) ;
MAIN_CreateMainWindow ( ) ;
Globals . hAccel = LoadAcceleratorsW ( Globals . hInstance , MAKEINTRESOURCEW ( IDA_ACCEL ) ) ;
STRING_LoadMenus ( ) ;
MAIN_CreateMDIWindow ( ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Load all the groups */
// MAIN_CreateGroups();
MAIN_LoadGroups ( ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Load the Startup group: start the initial applications */
MAIN_AutoStart ( ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Message loop */
while ( GetMessageW ( & msg , NULL , 0 , 0 ) )
{
if ( ! TranslateMDISysAccel ( Globals . hMDIWnd , & msg ) & &
! TranslateAcceleratorW ( Globals . hMainWnd , Globals . hAccel , & msg ) )
{
TranslateMessage ( & msg ) ;
DispatchMessageW ( & msg ) ;
}
}
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
Quit :
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Save the settings, close the registry keys and quit */
// MAIN_SaveSettings();
RegCloseKey ( Globals . hKeyCommonGroups ) ;
RegCloseKey ( Globals . hKeyUnicodeGroups ) ;
RegCloseKey ( Globals . hKeyAnsiGroups ) ;
RegCloseKey ( Globals . hKeyPMUnicodeGroups ) ;
RegCloseKey ( Globals . hKeyPMAnsiGroups ) ;
RegCloseKey ( Globals . hKeyPMCommonGroups ) ;
RegCloseKey ( Globals . hKeyPMSettings ) ;
RegCloseKey ( Globals . hKeyProgMan ) ;
return 0 ;
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_CreateGroups
*/
2016-05-11 22:21:53 +00:00
#if 0
static VOID MAIN_CreateGroups ( VOID )
2016-03-04 19:22:35 +00:00
{
CHAR buffer [ BUFFER_SIZE ] ;
CHAR szPath [ MAX_PATHNAME_LEN ] ;
CHAR key [ 20 ] , * ptr ;
/* Initialize groups according the `Order' entry of `progman.ini' */
GetPrivateProfileStringA ( " Settings " , " Order " , " " , buffer , sizeof ( buffer ) , Globals . lpszIniFile ) ;
ptr = buffer ;
while ( ptr < buffer + sizeof ( buffer ) )
{
int num , skip , ret ;
ret = sscanf ( ptr , " %d%n " , & num , & skip ) ;
if ( ret = = 0 )
MAIN_MessageBoxIDS_s ( IDS_FILE_READ_ERROR_s , Globals . lpszIniFile , IDS_ERROR , MB_OK ) ;
if ( ret ! = 1 ) break ;
sprintf ( key , " Group%d " , num ) ;
GetPrivateProfileStringA ( " Groups " , key , " " , szPath ,
sizeof ( szPath ) , Globals . lpszIniFile ) ;
if ( ! szPath [ 0 ] ) continue ;
GRPFILE_ReadGroupFile ( szPath ) ;
ptr + = skip ;
}
/* FIXME initialize other groups, not enumerated by `Order' */
}
2016-05-11 22:21:53 +00:00
# endif
static VOID MAIN_LoadGroups ( VOID )
{
}
2016-03-04 19:22:35 +00:00
/***********************************************************************
*
* MAIN_AutoStart
*/
2016-05-11 22:21:53 +00:00
static VOID MAIN_AutoStart ( VOID )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
LONG lRet ;
DWORD dwSize ;
DWORD dwType ;
PROGGROUP * hGroup ;
PROGRAM * hProgram ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
WCHAR buffer [ BUFFER_SIZE ] ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
dwSize = sizeof ( buffer ) ;
lRet = RegQueryValueExW ( Globals . hKeyPMSettings , L " Startup " , NULL , & dwType , ( LPBYTE ) buffer , & dwSize ) ;
if ( lRet ! = ERROR_SUCCESS | | dwType ! = REG_SZ )
return ;
for ( hGroup = Globals . hGroups ; hGroup ; hGroup = hGroup - > hNext )
{
if ( _wcsicmp ( buffer , hGroup - > hName ) = = 0 )
{
for ( hProgram = hGroup - > hPrograms ; hProgram ; hProgram = hProgram - > hNext )
PROGRAM_ExecuteProgram ( hProgram ) ;
}
}
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_MainWndProc
*/
2016-05-11 22:21:53 +00:00
static LRESULT CALLBACK MAIN_MainWndProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
switch ( uMsg )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
case WM_INITMENU :
{
PROGGROUP * hActiveGroup = GROUP_ActiveGroup ( ) ;
if ( hActiveGroup )
{
if ( PROGRAM_ActiveProgram ( hActiveGroup ) )
{
EnableMenuItem ( Globals . hFileMenu , PM_OPEN , MF_ENABLED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_MOVE , MF_ENABLED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_COPY , MF_ENABLED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_DELETE , MF_ENABLED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_ATTRIBUTES , MF_ENABLED ) ;
}
else
{
if ( ! hActiveGroup - > hWnd | | IsIconic ( hActiveGroup - > hWnd ) )
EnableMenuItem ( Globals . hFileMenu , PM_OPEN , MF_ENABLED ) ;
else
EnableMenuItem ( Globals . hFileMenu , PM_OPEN , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_MOVE , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_COPY , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_DELETE , MF_ENABLED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_ATTRIBUTES , MF_ENABLED ) ;
}
}
else
{
EnableMenuItem ( Globals . hFileMenu , PM_OPEN , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_MOVE , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_COPY , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_DELETE , MF_GRAYED ) ;
EnableMenuItem ( Globals . hFileMenu , PM_ATTRIBUTES , MF_GRAYED ) ;
}
CheckMenuItem ( Globals . hOptionMenu , PM_AUTO_ARRANGE ,
MF_BYCOMMAND | ( Globals . bAutoArrange ? MF_CHECKED : MF_UNCHECKED ) ) ;
CheckMenuItem ( Globals . hOptionMenu , PM_MIN_ON_RUN ,
MF_BYCOMMAND | ( Globals . bMinOnRun ? MF_CHECKED : MF_UNCHECKED ) ) ;
CheckMenuItem ( Globals . hOptionMenu , PM_SAVE_SETTINGS ,
MF_BYCOMMAND | ( Globals . bSaveSettings ? MF_CHECKED : MF_UNCHECKED ) ) ;
break ;
}
case WM_DESTROY :
if ( Globals . bSaveSettings )
MAIN_SaveSettings ( ) ;
PostQuitMessage ( 0 ) ;
break ;
case WM_COMMAND :
if ( LOWORD ( wParam ) < PM_FIRST_CHILD )
MAIN_MenuCommand ( hWnd , LOWORD ( wParam ) , lParam ) ;
break ;
2016-03-04 19:22:35 +00:00
}
2016-05-11 22:21:53 +00:00
return DefFrameProcW ( hWnd , Globals . hMDIWnd , uMsg , wParam , lParam ) ;
2016-03-04 19:22:35 +00:00
}
2016-05-11 22:21:53 +00:00
2016-03-04 19:22:35 +00:00
/***********************************************************************
*
* MAIN_MenuCommand
*/
static VOID MAIN_MenuCommand ( HWND hWnd , WPARAM wParam , LPARAM lParam )
{
2016-05-11 22:21:53 +00:00
#if 0
2016-03-04 19:22:35 +00:00
HLOCAL hActiveGroup = GROUP_ActiveGroup ( ) ;
HLOCAL hActiveProgram = PROGRAM_ActiveProgram ( hActiveGroup ) ;
HWND hActiveGroupWnd = GROUP_GroupWnd ( hActiveGroup ) ;
switch ( wParam )
{
/* Menu File */
case PM_NEW :
switch ( DIALOG_New ( ( hActiveGroupWnd & & ! IsIconic ( hActiveGroupWnd ) ) ?
PM_NEW_PROGRAM : PM_NEW_GROUP ) )
{
case PM_NEW_PROGRAM :
if ( hActiveGroup ) PROGRAM_NewProgram ( hActiveGroup ) ;
break ;
case PM_NEW_GROUP :
GROUP_NewGroup ( ) ;
break ;
}
break ;
case PM_DELETE :
if ( hActiveProgram )
{
if ( DIALOG_Delete ( IDS_DELETE_PROGRAM_s , PROGRAM_ProgramName ( hActiveProgram ) ) )
PROGRAM_DeleteProgram ( hActiveProgram , TRUE ) ;
}
else if ( hActiveGroup )
{
if ( DIALOG_Delete ( IDS_DELETE_GROUP_s , GROUP_GroupName ( hActiveGroup ) ) )
GROUP_DeleteGroup ( hActiveGroup ) ;
}
break ;
case PM_SAVE_SETTINGS :
Globals . bSaveSettings = ! Globals . bSaveSettings ;
CheckMenuItem ( Globals . hOptionMenu , PM_SAVE_SETTINGS ,
MF_BYCOMMAND | ( Globals . bSaveSettings ?
MF_CHECKED : MF_UNCHECKED ) ) ;
WritePrivateProfileStringA ( " Settings " , " SaveSettings " ,
Globals . bSaveSettings ? " 1 " : " 0 " ,
Globals . lpszIniFile ) ;
WritePrivateProfileStringA ( NULL , NULL , NULL , Globals . lpszIniFile ) ; /* flush it */
break ;
case PM_ARRANGE :
if ( hActiveGroupWnd & & ! IsIconic ( hActiveGroupWnd ) )
ArrangeIconicWindows ( hActiveGroupWnd ) ;
else
SendMessageW ( Globals . hMDIWnd , WM_MDIICONARRANGE , 0 , 0 ) ;
break ;
2016-03-05 01:27:27 +00:00
}
2016-05-11 22:21:53 +00:00
2016-03-05 08:45:08 +00:00
# endif
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
DWORD Value ;
PROGGROUP * hActiveGroup ;
PROGRAM * hActiveProgram ;
HWND hActiveGroupWnd ;
hActiveGroup = GROUP_ActiveGroup ( ) ;
hActiveProgram = PROGRAM_ActiveProgram ( hActiveGroup ) ;
hActiveGroupWnd = ( hActiveGroup ? hActiveGroup - > hWnd : NULL ) ;
switch ( wParam )
{
/* Menu File */
case PM_NEW :
{
BOOL Success ;
INT nResult ;
if ( ! hActiveGroupWnd | | IsIconic ( hActiveGroupWnd ) )
Success = DIALOG_New ( PM_NEW_GROUP , & nResult ) ;
else
Success = DIALOG_New ( PM_NEW_PROGRAM , & nResult ) ;
if ( ! Success )
break ;
if ( nResult & 1 )
{
GROUPFORMAT format ;
BOOL bIsCommonGroup ;
format = ( nResult & 0xC ) > > 2 ;
bIsCommonGroup = ( nResult & 2 ) ! = 0 ;
GROUP_NewGroup ( format , bIsCommonGroup ) ;
}
else if ( hActiveGroup )
{
PROGRAM_NewProgram ( hActiveGroup ) ;
}
break ;
}
case PM_OPEN :
if ( hActiveProgram )
PROGRAM_ExecuteProgram ( hActiveProgram ) ;
else if ( hActiveGroupWnd )
OpenIcon ( hActiveGroupWnd ) ;
break ;
case PM_MOVE :
case PM_COPY :
if ( hActiveProgram )
PROGRAM_CopyMoveProgram ( hActiveProgram , wParam = = PM_MOVE ) ;
break ;
case PM_DELETE :
{
if ( hActiveProgram )
{
if ( DIALOG_Delete ( IDS_DELETE_PROGRAM_s , hActiveProgram - > hName ) )
PROGRAM_DeleteProgram ( hActiveProgram , TRUE ) ;
}
else if ( hActiveGroup & & DIALOG_Delete ( IDS_DELETE_GROUP_s , hActiveGroup - > hName ) )
{
GROUP_DeleteGroup ( hActiveGroup ) ;
}
break ;
}
case PM_ATTRIBUTES :
if ( hActiveProgram )
PROGRAM_ModifyProgram ( hActiveProgram ) ;
else if ( hActiveGroup )
GROUP_ModifyGroup ( hActiveGroup ) ;
break ;
case PM_EXECUTE :
DIALOG_Execute ( ) ;
break ;
case PM_EXIT :
// MAIN_SaveSettings();
PostQuitMessage ( 0 ) ;
break ;
/* Menu Options */
case PM_AUTO_ARRANGE :
Globals . bAutoArrange = ! Globals . bAutoArrange ;
CheckMenuItem ( Globals . hOptionMenu , PM_AUTO_ARRANGE ,
MF_BYCOMMAND | ( Globals . bAutoArrange ? MF_CHECKED : MF_UNCHECKED ) ) ;
Value = Globals . bAutoArrange ;
RegSetValueExW ( Globals . hKeyPMSettings , L " AutoArrange " , 0 , REG_DWORD , ( LPBYTE ) & Value , sizeof ( Value ) ) ;
break ;
case PM_MIN_ON_RUN :
Globals . bMinOnRun = ! Globals . bMinOnRun ;
CheckMenuItem ( Globals . hOptionMenu , PM_MIN_ON_RUN ,
MF_BYCOMMAND | ( Globals . bMinOnRun ? MF_CHECKED : MF_UNCHECKED ) ) ;
Value = Globals . bMinOnRun ;
RegSetValueExW ( Globals . hKeyPMSettings , L " MinOnRun " , 0 , REG_DWORD , ( LPBYTE ) & Value , sizeof ( Value ) ) ;
break ;
case PM_SAVE_SETTINGS :
Globals . bSaveSettings = ! Globals . bSaveSettings ;
CheckMenuItem ( Globals . hOptionMenu , PM_SAVE_SETTINGS ,
MF_BYCOMMAND | ( Globals . bSaveSettings ? MF_CHECKED : MF_UNCHECKED ) ) ;
Value = Globals . bSaveSettings ;
RegSetValueExW ( Globals . hKeyPMSettings , L " SaveSettings " , 0 , REG_DWORD , ( LPBYTE ) & Value , sizeof ( Value ) ) ;
break ;
case PM_SAVE_SETTINGS_NOW :
MAIN_SaveSettings ( ) ;
break ;
/* Menu Windows */
case PM_OVERLAP :
SendMessageW ( Globals . hMDIWnd , WM_MDICASCADE , 0 , 0 ) ;
break ;
case PM_SIDE_BY_SIDE :
SendMessageW ( Globals . hMDIWnd , WM_MDITILE , MDITILE_VERTICAL , 0 ) ;
break ;
case PM_ARRANGE :
if ( ! hActiveGroupWnd | | IsIconic ( hActiveGroupWnd ) )
SendMessageW ( Globals . hMDIWnd , WM_MDIICONARRANGE , 0 , 0 ) ;
else
SendMessageA ( hActiveGroup - > hListView , LVM_ARRANGE , 0 , 0 ) ;
break ;
/* Menu Help */
case PM_CONTENTS :
if ( ! WinHelpW ( Globals . hMainWnd , L " progman.hlp " , HELP_CONTENTS , 0 ) )
MAIN_MessageBoxIDS ( IDS_WINHELP_ERROR , IDS_ERROR , MB_OK ) ;
break ;
case PM_ABOUT :
2016-05-12 19:54:53 +00:00
ShellAboutW ( hWnd , szTitle , NULL , Globals . hMainIcon ) ;
2016-05-11 22:21:53 +00:00
break ;
default :
MAIN_MessageBoxIDS ( IDS_NOT_IMPLEMENTED , IDS_ERROR , MB_OK ) ;
break ;
2016-03-04 19:22:35 +00:00
}
2016-05-11 22:21:53 +00:00
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_RegisterMainWinClass
*/
2016-05-11 22:21:53 +00:00
static ATOM MAIN_RegisterMainWinClass ( VOID )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
WNDCLASSW wndClass ;
wndClass . style = CS_HREDRAW | CS_VREDRAW ;
wndClass . lpfnWndProc = MAIN_MainWndProc ;
wndClass . cbClsExtra = 0 ;
wndClass . cbWndExtra = 0 ;
wndClass . hInstance = Globals . hInstance ;
2016-05-12 19:54:53 +00:00
wndClass . hIcon = Globals . hMainIcon ;
2024-07-01 16:05:46 +00:00
wndClass . hCursor = LoadCursorW ( NULL , IDC_ARROW ) ;
2016-05-11 22:21:53 +00:00
wndClass . hbrBackground = ( HBRUSH ) GetStockObject ( NULL_BRUSH ) ;
wndClass . lpszMenuName = NULL ;
wndClass . lpszClassName = STRING_MAIN_WIN_CLASS_NAME ;
return RegisterClassW ( & wndClass ) ;
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_CreateMainWindow
*/
2016-05-11 22:21:53 +00:00
static VOID MAIN_CreateMainWindow ( VOID )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
INT left , top , right , bottom ;
INT width , height ;
INT nCmdShow ;
WCHAR buffer [ 100 ] ;
LONG lRet ;
DWORD dwSize ;
DWORD dwType ;
Globals . hMDIWnd = NULL ;
Globals . hMainMenu = NULL ;
/* Get the geometry of the main window */
dwSize = sizeof ( buffer ) ;
lRet = RegQueryValueExW ( Globals . hKeyPMSettings , L " Window " , NULL , & dwType , ( LPBYTE ) buffer , & dwSize ) ;
if ( lRet ! = ERROR_SUCCESS | | dwType ! = REG_SZ )
buffer [ 0 ] = ' \0 ' ;
if ( swscanf ( buffer , L " %d %d %d %d %d " , & left , & top , & right , & bottom , & nCmdShow ) = = 5 )
{
width = right - left ;
height = bottom - top ;
}
else
{
left = top = width = height = CW_USEDEFAULT ;
nCmdShow = SW_SHOWNORMAL ;
}
/* Create the main window */
Globals . hMainWnd =
CreateWindowW ( STRING_MAIN_WIN_CLASS_NAME ,
szTitle ,
WS_OVERLAPPEDWINDOW , // /* | WS_CLIPSIBLINGS | WS_CLIPCHILDREN */
left , top , width , height ,
NULL , NULL ,
Globals . hInstance ,
NULL ) ;
MAIN_SetMainWindowTitle ( ) ;
ShowWindow ( Globals . hMainWnd , nCmdShow ) ;
UpdateWindow ( Globals . hMainWnd ) ;
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_CreateMDIWindow
*/
2016-05-11 22:21:53 +00:00
static VOID MAIN_CreateMDIWindow ( VOID )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
CLIENTCREATESTRUCT ccs ;
RECT rect ;
/* Get the geometry of the MDI window */
GetClientRect ( Globals . hMainWnd , & rect ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
ccs . hWindowMenu = Globals . hWindowsMenu ;
ccs . idFirstChild = PM_FIRST_CHILD ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Create MDI Window */
Globals . hMDIWnd =
CreateWindowW ( WC_MDICLIENT , NULL , WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL , // WS_CHILDWINDOW | ...
rect . left , rect . top ,
rect . right - rect . left , rect . bottom - rect . top ,
Globals . hMainWnd , 0 ,
Globals . hInstance , & ccs ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
/* Reset the background of the MDI client window (default: COLOR_APPWORKSPACE + 1) */
SetClassLongPtrW ( Globals . hMDIWnd , GCLP_HBRBACKGROUND , ( COLOR_WINDOW + 1 ) ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
ShowWindow ( Globals . hMDIWnd , SW_SHOW ) ;
UpdateWindow ( Globals . hMDIWnd ) ;
2016-03-04 19:22:35 +00:00
}
/**********************************************************************/
/***********************************************************************
*
* MAIN_MessageBoxIDS
*/
INT MAIN_MessageBoxIDS ( UINT ids_text , UINT ids_title , WORD type )
{
2016-05-11 22:21:53 +00:00
WCHAR text [ MAX_STRING_LEN ] ;
WCHAR title [ MAX_STRING_LEN ] ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
LoadStringW ( Globals . hInstance , ids_text , text , ARRAYSIZE ( text ) ) ;
LoadStringW ( Globals . hInstance , ids_title , title , ARRAYSIZE ( title ) ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
return MessageBoxW ( Globals . hMainWnd , text , title , type ) ;
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_MessageBoxIDS_s
*/
2016-05-11 22:21:53 +00:00
INT MAIN_MessageBoxIDS_s ( UINT ids_text , LPCWSTR str , UINT ids_title , WORD type )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
WCHAR text [ MAX_STRING_LEN ] ;
WCHAR title [ MAX_STRING_LEN ] ;
WCHAR newtext [ MAX_STRING_LEN + MAX_PATHNAME_LEN ] ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
LoadStringW ( Globals . hInstance , ids_text , text , ARRAYSIZE ( text ) ) ;
LoadStringW ( Globals . hInstance , ids_title , title , ARRAYSIZE ( title ) ) ;
wsprintfW ( newtext , text , str ) ;
2016-03-04 19:22:35 +00:00
2016-05-11 22:21:53 +00:00
return MessageBoxW ( Globals . hMainWnd , newtext , title , type ) ;
2016-03-04 19:22:35 +00:00
}
/***********************************************************************
*
* MAIN_ReplaceString
*/
2016-05-11 22:21:53 +00:00
VOID MAIN_ReplaceString ( LPWSTR * string , LPWSTR replace )
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
LPWSTR newstring ;
newstring = Alloc ( HEAP_ZERO_MEMORY , ( wcslen ( replace ) + 1 ) * sizeof ( WCHAR ) ) ;
if ( newstring )
{
wcscpy ( newstring , replace ) ;
* string = newstring ;
}
else
2016-03-04 19:22:35 +00:00
{
2016-05-11 22:21:53 +00:00
MAIN_MessageBoxIDS ( IDS_OUT_OF_MEMORY , IDS_ERROR , MB_OK ) ;
2016-03-04 19:22:35 +00:00
}
}