mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 12:26:32 +00:00
1a1025011f
Fix wrong MAKEINTRESOURCEW() macro usage cases in LoadCursorW() system-wide. MSDN documentation for this function states we need to use MAKEINTRESOURCEW() macro only for internal application-defined cursors (loaded from the app instance specified by hInstance parameter), but not for system-defined cursors (those begin with IDC_* prefix), in case when hInstance is NULL. So get rid from MAKEINTRESOURCEW() macro usage for all cases when hInstance parameter is NULL. And on the contrary, when hInstance is valid and points to the application instance, then use it for the resource identifier.
1207 lines
35 KiB
C
1207 lines
35 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
/*
|
|
* 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)
|
|
*/
|
|
|
|
#include "progman.h"
|
|
|
|
#include <shellapi.h>
|
|
|
|
#define WC_MDICLIENTA "MDICLIENT"
|
|
#define WC_MDICLIENTW L"MDICLIENT"
|
|
|
|
#ifdef UNICODE
|
|
#define WC_MDICLIENT WC_MDICLIENTW
|
|
#else
|
|
#define WC_MDICLIENT WC_MDICLIENTA
|
|
#endif
|
|
|
|
GLOBALS Globals;
|
|
|
|
static VOID MAIN_LoadGroups(VOID);
|
|
static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
|
|
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)
|
|
{
|
|
StringCbPrintfW(caption, size, L"%s - %s\\%s", szTitle, lpDomainName, lpUserName);
|
|
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);
|
|
StringCbPrintfW(buffer, sizeof(buffer),
|
|
L"%d %d %d %d %d",
|
|
WndPl.rcNormalPosition.left,
|
|
WndPl.rcNormalPosition.top,
|
|
WndPl.rcNormalPosition.right,
|
|
WndPl.rcNormalPosition.bottom,
|
|
WndPl.showCmd);
|
|
|
|
dwSize = wcslen(buffer) * sizeof(WCHAR);
|
|
RegSetValueExW(Globals.hKeyPMSettings, L"Window", 0, REG_SZ, (LPBYTE)buffer, dwSize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* WinMain
|
|
*/
|
|
|
|
INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow)
|
|
{
|
|
MSG msg;
|
|
INITCOMMONCONTROLSEX icex;
|
|
|
|
/*
|
|
* 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);
|
|
|
|
Globals.hInstance = hInstance;
|
|
Globals.hGroups = NULL;
|
|
Globals.hActiveGroup = NULL;
|
|
|
|
/* Load Program Manager's settings */
|
|
MAIN_LoadSettings();
|
|
|
|
/* Load the default icons */
|
|
Globals.hDefaultIcon = LoadIconW(NULL, MAKEINTRESOURCEW(IDI_WINLOGO));
|
|
Globals.hMainIcon = LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(IDI_APPICON));
|
|
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!
|
|
{
|
|
if (!MAIN_RegisterMainWinClass()) goto Quit;
|
|
if (!GROUP_RegisterGroupWinClass()) goto Quit;
|
|
}
|
|
|
|
/* 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();
|
|
|
|
/* Load all the groups */
|
|
// MAIN_CreateGroups();
|
|
MAIN_LoadGroups();
|
|
|
|
/* Load the Startup group: start the initial applications */
|
|
MAIN_AutoStart();
|
|
|
|
/* Message loop */
|
|
while (GetMessageW(&msg, NULL, 0, 0))
|
|
{
|
|
if (!TranslateMDISysAccel(Globals.hMDIWnd, &msg) &&
|
|
!TranslateAcceleratorW(Globals.hMainWnd, Globals.hAccel, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
}
|
|
}
|
|
|
|
Quit:
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_CreateGroups
|
|
*/
|
|
|
|
#if 0
|
|
static VOID MAIN_CreateGroups(VOID)
|
|
{
|
|
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' */
|
|
}
|
|
#endif
|
|
|
|
static VOID MAIN_LoadGroups(VOID)
|
|
{
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_AutoStart
|
|
*/
|
|
|
|
static VOID MAIN_AutoStart(VOID)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
PROGGROUP* hGroup;
|
|
PROGRAM* hProgram;
|
|
|
|
WCHAR buffer[BUFFER_SIZE];
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_MainWndProc
|
|
*/
|
|
|
|
static LRESULT CALLBACK MAIN_MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
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;
|
|
}
|
|
|
|
return DefFrameProcW(hWnd, Globals.hMDIWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_MenuCommand
|
|
*/
|
|
|
|
static VOID MAIN_MenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#if 0
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
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:
|
|
ShellAboutW(hWnd, szTitle, NULL, Globals.hMainIcon);
|
|
break;
|
|
|
|
default:
|
|
MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_RegisterMainWinClass
|
|
*/
|
|
|
|
static ATOM MAIN_RegisterMainWinClass(VOID)
|
|
{
|
|
WNDCLASSW wndClass;
|
|
|
|
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
|
wndClass.lpfnWndProc = MAIN_MainWndProc;
|
|
wndClass.cbClsExtra = 0;
|
|
wndClass.cbWndExtra = 0;
|
|
wndClass.hInstance = Globals.hInstance;
|
|
wndClass.hIcon = Globals.hMainIcon;
|
|
wndClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
|
wndClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
|
|
wndClass.lpszMenuName = NULL;
|
|
wndClass.lpszClassName = STRING_MAIN_WIN_CLASS_NAME;
|
|
|
|
return RegisterClassW(&wndClass);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_CreateMainWindow
|
|
*/
|
|
|
|
static VOID MAIN_CreateMainWindow(VOID)
|
|
{
|
|
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);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_CreateMDIWindow
|
|
*/
|
|
|
|
static VOID MAIN_CreateMDIWindow(VOID)
|
|
{
|
|
CLIENTCREATESTRUCT ccs;
|
|
RECT rect;
|
|
|
|
/* Get the geometry of the MDI window */
|
|
GetClientRect(Globals.hMainWnd, &rect);
|
|
|
|
ccs.hWindowMenu = Globals.hWindowsMenu;
|
|
ccs.idFirstChild = PM_FIRST_CHILD;
|
|
|
|
/* 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);
|
|
|
|
/* Reset the background of the MDI client window (default: COLOR_APPWORKSPACE + 1) */
|
|
SetClassLongPtrW(Globals.hMDIWnd, GCLP_HBRBACKGROUND, (COLOR_WINDOW + 1));
|
|
|
|
ShowWindow(Globals.hMDIWnd, SW_SHOW);
|
|
UpdateWindow(Globals.hMDIWnd);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_MessageBoxIDS
|
|
*/
|
|
INT MAIN_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
|
|
{
|
|
WCHAR text[MAX_STRING_LEN];
|
|
WCHAR title[MAX_STRING_LEN];
|
|
|
|
LoadStringW(Globals.hInstance, ids_text , text , ARRAYSIZE(text));
|
|
LoadStringW(Globals.hInstance, ids_title, title, ARRAYSIZE(title));
|
|
|
|
return MessageBoxW(Globals.hMainWnd, text, title, type);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_MessageBoxIDS_s
|
|
*/
|
|
INT MAIN_MessageBoxIDS_s(UINT ids_text, LPCWSTR str, UINT ids_title, WORD type)
|
|
{
|
|
WCHAR text[MAX_STRING_LEN];
|
|
WCHAR title[MAX_STRING_LEN];
|
|
WCHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
|
|
|
|
LoadStringW(Globals.hInstance, ids_text , text , ARRAYSIZE(text));
|
|
LoadStringW(Globals.hInstance, ids_title, title, ARRAYSIZE(title));
|
|
wsprintfW(newtext, text, str);
|
|
|
|
return MessageBoxW(Globals.hMainWnd, newtext, title, type);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* MAIN_ReplaceString
|
|
*/
|
|
|
|
VOID MAIN_ReplaceString(LPWSTR* string, LPWSTR replace)
|
|
{
|
|
LPWSTR newstring;
|
|
|
|
newstring = Alloc(HEAP_ZERO_MEMORY, (wcslen(replace) + 1) * sizeof(WCHAR));
|
|
if (newstring)
|
|
{
|
|
wcscpy(newstring, replace);
|
|
*string = newstring;
|
|
}
|
|
else
|
|
{
|
|
MAIN_MessageBoxIDS(IDS_OUT_OF_MEMORY, IDS_ERROR, MB_OK);
|
|
}
|
|
}
|