433 lines
12 KiB
C++
433 lines
12 KiB
C++
// **************************************************************************
|
|
//
|
|
// RunOnce.Cpp
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1992-1993
|
|
// All rights reserved
|
|
//
|
|
// RunOnce wrapper. This encapsulates all applications that would like
|
|
// to run the first time we re-boot. It lists these apps for the user
|
|
// and allows the user to launce the apps (like apple at ease).
|
|
//
|
|
// 5 June 1994 FelixA Started
|
|
// 8 June Felix Defined registry strings and functionality.
|
|
// Got small buttons displayed, but not working.
|
|
// 9 June Felix Both big and small buttons. Nice UI.
|
|
// Got single click app launching.
|
|
//
|
|
// 23 June Felix Moving it to a Chicago make thingy not Dolphin
|
|
//
|
|
// *************************************************************************/
|
|
//
|
|
#include "iernonce.h"
|
|
#include "resource.h"
|
|
|
|
|
|
#define CXBORDER 3
|
|
|
|
|
|
// globals
|
|
HDC g_hdcMem = NULL; // Run time can be set for big or small buttons.
|
|
int g_cxSmIcon = 0; // Icon sizes.
|
|
SIZE g_SizeTextExt; // Extent of text in buttons.
|
|
HFONT g_hfont = NULL;
|
|
HFONT g_hBoldFont = NULL;
|
|
HBRUSH g_hbrBkGnd = NULL;
|
|
ARGSINFO g_aiArgs;
|
|
|
|
|
|
// prototypes
|
|
BOOL CreateGlobals(HWND hwndCtl);
|
|
BOOL RunOnceFill(HWND hWndLB);
|
|
void ShrinkToFit(HWND hWnd, HWND hLb);
|
|
DWORD RunAppsInList(LPVOID lp);
|
|
LRESULT HandleLBMeasureItem(HWND hwndLB, MEASUREITEMSTRUCT *lpmi);
|
|
LRESULT HandleLBDrawItem(HWND hwndLB, DRAWITEMSTRUCT *lpdi);
|
|
void DestroyGlobals(void);
|
|
|
|
|
|
INT_PTR CALLBACK DlgProcRunOnceEx(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static HANDLE s_hThread = NULL;
|
|
DWORD dwThread;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
g_aiArgs = *((ARGSINFO *) lParam);
|
|
CreateGlobals(hWnd);
|
|
SetWindowPos(hWnd, NULL, 32, 32, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
RunOnceFill(GetDlgItem(hWnd, IDC_LIST2));
|
|
// Now calculate the size needed for the LB and resize LB and parent.
|
|
ShrinkToFit(hWnd, GetDlgItem(hWnd, IDC_LIST2));
|
|
if ((s_hThread = CreateThread(NULL, 0, RunAppsInList, (LPVOID) GetDlgItem(hWnd, IDC_LIST2), 0, &dwThread)) == NULL)
|
|
PostMessage(hWnd, WM_FINISHED, 0, 0L);
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
if (g_aiArgs.dwFlags & RRA_WAIT)
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
return TRUE;
|
|
|
|
case WM_MEASUREITEM:
|
|
if (((MEASUREITEMSTRUCT *) lParam)->CtlType == ODT_LISTBOX)
|
|
return HandleLBMeasureItem(hWnd, (MEASUREITEMSTRUCT *) lParam);
|
|
else
|
|
return FALSE;
|
|
|
|
case WM_DRAWITEM:
|
|
if (((DRAWITEMSTRUCT *) lParam)->CtlType == ODT_LISTBOX)
|
|
return HandleLBDrawItem(hWnd, (DRAWITEMSTRUCT *) lParam);
|
|
else
|
|
return FALSE;
|
|
|
|
case WM_CTLCOLORLISTBOX:
|
|
SetTextColor((HDC) wParam, GetSysColor(COLOR_BTNTEXT));
|
|
SetBkColor((HDC) wParam, GetSysColor(COLOR_BTNFACE));
|
|
return (LRESULT) g_hbrBkGnd;
|
|
|
|
case WM_FINISHED:
|
|
if (s_hThread != NULL)
|
|
{
|
|
while (MsgWaitForMultipleObjects(1, &s_hThread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
|
|
{
|
|
MSG msg;
|
|
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
CloseHandle(s_hThread);
|
|
s_hThread = NULL;
|
|
}
|
|
DestroyGlobals();
|
|
EndDialog(hWnd, 0);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPSTR MakeAnsiStrFromWide(LPWSTR pwsz)
|
|
{
|
|
LPSTR psz;
|
|
int i;
|
|
|
|
// arg checking.
|
|
//
|
|
if (!pwsz)
|
|
return NULL;
|
|
|
|
// compute the length
|
|
//
|
|
i = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL);
|
|
if (i <= 0) return NULL;
|
|
|
|
psz = (LPSTR) CoTaskMemAlloc(i * sizeof(CHAR));
|
|
|
|
if (!psz) return NULL;
|
|
WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, i, NULL, NULL);
|
|
psz[i - 1] = 0;
|
|
return psz;
|
|
}
|
|
|
|
|
|
BOOL CreateGlobals(HWND hwndCtl)
|
|
{
|
|
|
|
LOGFONT lf;
|
|
HDC hdc;
|
|
HFONT hfontOld;
|
|
|
|
g_cxSmIcon = GetSystemMetrics(SM_CXSMICON);
|
|
g_hbrBkGnd = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
|
|
|
if ((hfontOld = (HFONT) (WORD) SendMessage(hwndCtl, WM_GETFONT, 0, 0L)) != NULL)
|
|
{
|
|
if (GetObject(hfontOld, sizeof(LOGFONT), (LPSTR) &lf))
|
|
{
|
|
// The CreateFontIndirect calls in IESetup Wzd works correctly on
|
|
// all platforms... and they convert the Font name to Ansi
|
|
// Hence to solve the Thai NT/Thai Win9x problem, we also convert
|
|
// the font name to Ansi before calling CreateFontIndirect.
|
|
|
|
// #58923: Now the FaceName returned by GetObject is not UNICODE on all
|
|
// platforms. On Win9x, it is Ansi and this screws up things when
|
|
// we call MakeAnsiStrFromWide on it. Hence to avoid problems, check
|
|
// if returned FaceName is Wide <asumming FaceName always has more
|
|
// than 2 chars in it.>
|
|
if (lf.lfFaceName[1] == '\0')
|
|
{
|
|
LPSTR pszAnsiName;
|
|
|
|
pszAnsiName = MakeAnsiStrFromWide((unsigned short *)lf.lfFaceName);
|
|
lstrcpy((char *)lf.lfFaceName, pszAnsiName);
|
|
CoTaskMemFree((LPVOID)pszAnsiName);
|
|
}
|
|
|
|
lf.lfWeight = 400;
|
|
g_hfont = CreateFontIndirect(&lf);
|
|
|
|
lf.lfWeight = 700;
|
|
g_hBoldFont = CreateFontIndirect(&lf);
|
|
}
|
|
}
|
|
|
|
if (g_hfont)
|
|
{
|
|
TCHAR *szLotsaWs = TEXT("WWWWWWWWWW");
|
|
|
|
// Calc sensible size for text in buttons.
|
|
hdc = GetDC(NULL);
|
|
hfontOld = (HFONT) SelectObject(hdc, g_hfont);
|
|
GetTextExtentPoint(hdc, szLotsaWs, lstrlen(szLotsaWs), &g_SizeTextExt);
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RunOnceFill()
|
|
// Fills the List box in the run-once dlg.
|
|
//
|
|
// ENTRY:
|
|
// HWND of the thing to fill.
|
|
//
|
|
// EXIT:
|
|
// <Params>
|
|
//
|
|
//***************************************************************************
|
|
BOOL RunOnceFill(HWND hWndLB)
|
|
{
|
|
RunOnceExSection *pCurrentRunOnceExSection;
|
|
int iSectionIndex;
|
|
|
|
// if Title value is present, display it
|
|
if (*g_szTitleString)
|
|
SetWindowText(GetParent(hWndLB), g_szTitleString);
|
|
|
|
for (iSectionIndex = 0; iSectionIndex < g_aiArgs.iNumberOfSections; iSectionIndex++)
|
|
{
|
|
pCurrentRunOnceExSection = (RunOnceExSection *) DPA_GetPtr(g_aiArgs.hdpaSections, iSectionIndex);
|
|
|
|
if (*pCurrentRunOnceExSection->m_szDisplayName != TEXT('\0'))
|
|
SendMessage(hWndLB, LB_ADDSTRING, 0, (LPARAM) pCurrentRunOnceExSection->m_szDisplayName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// ShrinkToFit()
|
|
// Makes the List box no bigger then it has to be
|
|
// makes the parent window rsize to the LB size.
|
|
//
|
|
// ENTRY:
|
|
// hwnd Parent
|
|
// hwnd List box
|
|
//
|
|
// EXIT:
|
|
//
|
|
//***************************************************************************
|
|
void ShrinkToFit(HWND hWnd, HWND hLb)
|
|
{
|
|
LONG lCount;
|
|
LONG lNumItems;
|
|
LONG lTotalHeight;
|
|
LONG lHeight;
|
|
RECT rWnd;
|
|
LONG lChange;
|
|
|
|
lTotalHeight = 0;
|
|
lNumItems = (LONG)SendMessage(hLb, LB_GETCOUNT, 0, 0L);
|
|
|
|
for (lCount = 0; lCount < lNumItems; lCount++)
|
|
{
|
|
lHeight = (LONG)SendMessage(hLb, LB_GETITEMHEIGHT, lCount, 0L);
|
|
lTotalHeight += lHeight;
|
|
}
|
|
|
|
// Set the height of the ListBox to the number of items in it.
|
|
GetWindowRect(hLb, &rWnd);
|
|
SetWindowPos(hLb, hWnd, 0, 0, rWnd.right - rWnd.left - (CXBORDER * 2 + g_cxSmIcon), lTotalHeight, SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER);
|
|
|
|
// Work out how much it changed in height
|
|
lChange = lTotalHeight - (rWnd.bottom - rWnd.top);
|
|
|
|
// Size the parent to fit around the child.
|
|
GetWindowRect(hWnd, &rWnd);
|
|
SetWindowPos(hWnd, 0, 0, 0, rWnd.right - rWnd.left, rWnd.bottom - rWnd.top + lChange, SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RunAppsInList()
|
|
// Enumerates all the items in the list box, spawning each in turn.
|
|
//
|
|
// ENTRY:
|
|
// HWND of Parent.
|
|
//
|
|
// EXIT:
|
|
// <Params>
|
|
//
|
|
//***************************************************************************
|
|
DWORD RunAppsInList(LPVOID lp)
|
|
{
|
|
ProcessSections(g_aiArgs.hkeyParent, g_aiArgs.pszSubkey, g_aiArgs.dwFlags, g_aiArgs.hdpaSections, g_aiArgs.iNumberOfSections, (HWND) lp);
|
|
|
|
// terminate the dialog box
|
|
PostMessage(GetParent((HWND) lp), WM_FINISHED, 0, 0L);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
LRESULT HandleLBMeasureItem(HWND hDlg, MEASUREITEMSTRUCT *lpmi)
|
|
{
|
|
RECT rWnd;
|
|
int wWnd;
|
|
HDC hDC;
|
|
HFONT hfontOld;
|
|
TCHAR szText[MAX_ENTRYNAME];
|
|
|
|
// Get the Height and Width of the child window
|
|
GetWindowRect(hDlg, &rWnd);
|
|
wWnd = rWnd.right - rWnd.left;
|
|
|
|
lpmi->itemWidth = wWnd;
|
|
|
|
hDC = GetDC(NULL);
|
|
|
|
if ((hfontOld = (HFONT) SelectObject(hDC, g_hBoldFont)) != 0)
|
|
{
|
|
rWnd.top = 0;
|
|
rWnd.left = CXBORDER * 2 + g_cxSmIcon;
|
|
rWnd.right = lpmi->itemWidth - rWnd.left - CXBORDER * 2 - g_cxSmIcon;
|
|
rWnd.bottom = 0;
|
|
|
|
*szText = TEXT('\0');
|
|
SendMessage(GetDlgItem(hDlg, IDC_LIST2), LB_GETTEXT, (WPARAM) lpmi->itemID, (LPARAM) szText);
|
|
DrawText(hDC, szText, lstrlen(szText), &rWnd, DT_CALCRECT | DT_WORDBREAK);
|
|
|
|
SelectObject(hDC, hfontOld);
|
|
}
|
|
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
lpmi->itemHeight = rWnd.bottom + CXBORDER * 2;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// HandleLBDrawItem()
|
|
// Draws the Title, Text, and icon for an entry.
|
|
//
|
|
// ENTRY:
|
|
// HWND and the Item to draw.
|
|
//
|
|
// EXIT:
|
|
// <Params>
|
|
//
|
|
//***************************************************************************
|
|
LRESULT HandleLBDrawItem(HWND hDlg, DRAWITEMSTRUCT *lpdi)
|
|
{
|
|
RECT rc;
|
|
HFONT hfontOld;
|
|
int xArrow,y;
|
|
BITMAP bm;
|
|
HGDIOBJ hbmArrow, hbmOld;
|
|
TCHAR szText[MAX_ENTRYNAME];
|
|
|
|
// Don't draw anything for an empty list.
|
|
if ((int) lpdi->itemID < 0)
|
|
return TRUE;
|
|
|
|
if ((lpdi->itemAction & ODA_SELECT) || (lpdi->itemAction & ODA_DRAWENTIRE))
|
|
{
|
|
// Put in the Title text
|
|
hfontOld = (HFONT) SelectObject(lpdi->hDC, (lpdi->itemState & ODS_SELECTED) ? g_hBoldFont : g_hfont);
|
|
|
|
ExtTextOut(lpdi->hDC, lpdi->rcItem.left + CXBORDER * 2 + g_cxSmIcon, lpdi->rcItem.top + CXBORDER,
|
|
ETO_OPAQUE, &lpdi->rcItem, NULL, 0, NULL);
|
|
|
|
rc.top = lpdi->rcItem.top + CXBORDER;
|
|
rc.left = lpdi->rcItem.left + CXBORDER * 2 + g_cxSmIcon;
|
|
rc.right = lpdi->rcItem.right;
|
|
rc.bottom = lpdi->rcItem.bottom;
|
|
|
|
*szText = TEXT('\0');
|
|
SendMessage(GetDlgItem(hDlg, IDC_LIST2), LB_GETTEXT, (WPARAM) lpdi->itemID, (LPARAM) szText);
|
|
DrawText(lpdi->hDC, szText, lstrlen(szText), &rc, DT_WORDBREAK);
|
|
|
|
SelectObject(lpdi->hDC, hfontOld);
|
|
|
|
// Draw the little triangle thingies.
|
|
if (lpdi->itemState & ODS_SELECTED)
|
|
{
|
|
if (!g_hdcMem)
|
|
{
|
|
g_hdcMem = CreateCompatibleDC(lpdi->hDC);
|
|
}
|
|
|
|
if (g_hdcMem)
|
|
{
|
|
hbmArrow = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
|
|
GetObject(hbmArrow, sizeof(bm), &bm);
|
|
|
|
hbmOld = SelectObject(g_hdcMem, hbmArrow);
|
|
|
|
xArrow = lpdi->rcItem.left + CXBORDER;
|
|
y = ((g_SizeTextExt.cy - bm.bmHeight) / 2) + CXBORDER + lpdi->rcItem.top;
|
|
BitBlt(lpdi->hDC, xArrow, y, bm.bmWidth, bm.bmHeight, g_hdcMem, 0, 0, SRCAND);
|
|
|
|
SelectObject(g_hdcMem, hbmOld);
|
|
|
|
DeleteObject(hbmArrow);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void DestroyGlobals(void)
|
|
{
|
|
if (g_hfont)
|
|
{
|
|
DeleteObject(g_hfont);
|
|
g_hfont = NULL;
|
|
}
|
|
|
|
if (g_hBoldFont)
|
|
{
|
|
DeleteObject(g_hBoldFont);
|
|
g_hBoldFont = NULL;
|
|
}
|
|
|
|
if (g_hbrBkGnd)
|
|
{
|
|
DeleteObject(g_hbrBkGnd);
|
|
g_hbrBkGnd = NULL;
|
|
}
|
|
}
|