Modified: trunk/reactos/lib/aclui/aclui.c
Modified: trunk/reactos/lib/aclui/aclui.xml
Modified: trunk/reactos/lib/aclui/aclui_De.rc
Modified: trunk/reactos/lib/aclui/aclui_En.rc
Modified: trunk/reactos/lib/aclui/aclui_Sv.rc
Modified: trunk/reactos/lib/aclui/acluilib.h
Added: trunk/reactos/lib/aclui/checklist.c
Modified: trunk/reactos/lib/aclui/misc.c
Modified: trunk/reactos/lib/aclui/resource.h
--- trunk/reactos/lib/aclui/aclui.c 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/aclui.c 2005-07-01 23:33:34 UTC (rev 16374)
@@ -30,32 +30,6 @@
HINSTANCE hDllInstance;
-static LPARAM
-ListViewGetSelectedItemData(IN HWND hwnd)
-{
- int Index;
-
- Index = ListView_GetNextItem(hwnd,
- -1,
- LVNI_SELECTED);
- if (Index != -1)
- {
- LVITEM li;
-
- li.mask = LVIF_PARAM;
- li.iItem = Index;
- li.iSubItem = 0;
-
- if (ListView_GetItem(hwnd,
- &li))
- {
- return li.lParam;
- }
- }
-
- return 0;
-}
-
static VOID
DestroySecurityPage(IN PSECURITY_PAGE sp)
{
@@ -363,6 +337,38 @@
}
}
+static INT
+AddAceListEntry(IN PSECURITY_PAGE sp,
+ IN PACE_LISTITEM AceListItem,
+ IN INT Index,
+ IN BOOL Selected)
+{
+ LVITEM li;
+
+ li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
+ li.iItem = Index;
+ li.iSubItem = 0;
+ li.state = (Selected ? LVIS_SELECTED : 0);
+ li.stateMask = LVIS_SELECTED;
+ li.pszText = (AceListItem->DisplayString != NULL ? AceListItem->DisplayString : AceListItem->AccountName);
+ switch (AceListItem->SidNameUse)
+ {
+ case SidTypeUser:
+ li.iImage = 0;
+ break;
+ case SidTypeGroup:
+ li.iImage = 1;
+ break;
+ default:
+ li.iImage = -1;
+ break;
+ }
+ li.lParam = (LPARAM)AceListItem;
+
+ return ListView_InsertItem(sp->hWndAceList,
+ &li);
+}
+
static VOID
FillUsersGroupsList(IN PSECURITY_PAGE sp)
{
@@ -382,30 +388,10 @@
CurItem != NULL;
CurItem = CurItem->Next)
{
- LVITEM li;
-
- li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
- li.iItem = -1;
- li.iSubItem = 0;
- li.state = (CurItem == (PACE_LISTITEM)SelLParam ? LVIS_SELECTED : 0);
- li.stateMask = LVIS_SELECTED;
- li.pszText = (CurItem->DisplayString != NULL ? CurItem->DisplayString : CurItem->AccountName);
- switch (CurItem->SidNameUse)
- {
- case SidTypeUser:
- li.iImage = 0;
- break;
- case SidTypeGroup:
- li.iImage = 1;
- break;
- default:
- li.iImage = -1;
- break;
- }
- li.lParam = (LPARAM)CurItem;
-
- ListView_InsertItem(sp->hWndAceList,
- &li);
+ AddAceListEntry(sp,
+ CurItem,
+ -1,
+ (SelLParam == (LPARAM)CurItem));
}
EnableRedrawWindow(sp->hWndAceList);
@@ -417,7 +403,16 @@
rcLvClient.right);
}
+static VOID
+UpdateControlStates(IN PSECURITY_PAGE sp)
+{
+ BOOL UserOrGroupSelected;
+
+ UserOrGroupSelected = (ListViewGetSelectedItemData(sp->hWndAceList) != 0);
+ EnableWindow(sp->hBtnRemove, UserOrGroupSelected);
+}
+
static UINT CALLBACK
SecurityPageCallback(IN HWND hwnd,
IN UINT uMsg,
@@ -434,6 +429,7 @@
case PSPCB_RELEASE:
{
DestroySecurityPage(sp);
+ UnregisterCheckListControl();
return FALSE;
}
}
@@ -441,7 +437,30 @@
return FALSE;
}
+static VOID
+SetAceCheckListColumns(IN HWND hAceCheckList,
+ IN UINT Button,
+ IN HWND hLabel)
+{
+ POINT pt;
+ RECT rcLabel;
+ GetWindowRect(hLabel,
+ &rcLabel);
+ pt.y = 0;
+ pt.x = (rcLabel.right - rcLabel.left) / 2;
+ MapWindowPoints(hLabel,
+ hAceCheckList,
+ &pt,
+ 1);
+
+ SendMessage(hAceCheckList,
+ CLM_SETCHECKBOXCOLUMN,
+ Button,
+ pt.x);
+}
+
+
static INT_PTR CALLBACK
SecurityPageProc(IN HWND hwndDlg,
IN UINT uMsg,
@@ -452,6 +471,28 @@
switch(uMsg)
{
+ case WM_NOTIFY:
+ {
+ NMHDR *pnmh = (NMHDR*)lParam;
+ if (pnmh->idFrom == IDC_ACELIST)
+ {
+ sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg,
+ DWL_USER);
+ if (sp != NULL)
+ {
+ switch(pnmh->code)
+ {
+ case LVN_ITEMCHANGED:
+ {
+ UpdateControlStates(sp);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+
case WM_INITDIALOG:
{
sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
@@ -462,6 +503,8 @@
sp->hWnd = hwndDlg;
sp->hWndAceList = GetDlgItem(hwndDlg, IDC_ACELIST);
+ sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_ACELIST_REMOVE);
+ sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
/* save the pointer to the structure */
SetWindowLongPtr(hwndDlg,
@@ -491,7 +534,18 @@
ListView_InsertColumn(sp->hWndAceList, 0, &lvc);
FillUsersGroupsList(sp);
+
+ ListViewSelectItem(sp->hWndAceList,
+ 0);
+ /* calculate the columns of the allow/deny checkboxes */
+ SetAceCheckListColumns(sp->hAceCheckList,
+ CLB_ALLOW,
+ GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
+ SetAceCheckListColumns(sp->hAceCheckList,
+ CLB_DENY,
+ GetDlgItem(hwndDlg, IDC_LABEL_DENY));
+
/* FIXME - hide controls in case the flags aren't present */
}
break;
@@ -530,10 +584,16 @@
{
SetLastError(hRet);
- DPRINT("CreateSecurityPage() failed!\n");
+ DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
return NULL;
}
+ if (!RegisterCheckListControl(hDllInstance))
+ {
+ DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
+ return NULL;
+ }
+
sPage = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SECURITY_PAGE));
@@ -555,7 +615,7 @@
psp.lParam = (LPARAM)sPage;
psp.pfnCallback = SecurityPageCallback;
- if((ObjectInfo.dwFlags & SI_PAGE_TITLE) != 0 &&
+ if((ObjectInfo.dwFlags & SI_PAGE_TITLE) &&
ObjectInfo.pszPageTitle != NULL && ObjectInfo.pszPageTitle[0] != L'\0')
{
/* Set the page title if the flag is present and the string isn't empty */
@@ -618,7 +678,7 @@
psh.dwFlags = PSH_DEFAULT;
psh.hwndParent = hwndOwner;
psh.hInstance = hDllInstance;
- if((ObjectInfo.dwFlags & SI_PAGE_TITLE) != 0 &&
+ if((ObjectInfo.dwFlags & SI_PAGE_TITLE) &&
ObjectInfo.pszPageTitle != NULL && ObjectInfo.pszPageTitle[0] != L'\0')
{
/* Set the page title if the flag is present and the string isn't empty */
--- trunk/reactos/lib/aclui/aclui.xml 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/aclui.xml 2005-07-01 23:33:34 UTC (rev 16374)
@@ -10,8 +10,10 @@
<library>ntdll</library>
<library>kernel32</library>
<library>user32</library>
+ <library>gdi32</library>
<library>comctl32</library>
<file>aclui.c</file>
+ <file>checklist.c</file>
<file>misc.c</file>
<file>aclui.rc</file>
<pch>acluilib.h</pch>
--- trunk/reactos/lib/aclui/aclui_De.rc 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/aclui_De.rc 2005-07-01 23:33:34 UTC (rev 16374)
@@ -1,7 +1,7 @@
LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT
IDD_SECPAGE DIALOGEX 0, 0, 227, 215
-STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION
+STYLE DS_NOFAILCREATE | DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CAPTION
CAPTION "Sicherheit"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
@@ -9,8 +9,9 @@
CONTROL "", IDC_ACELIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 7, 17, 213, 66, WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE
PUSHBUTTON "&Hinzuf³gen...", IDC_ACELIST_ADD, 116, 87, 50, 14
PUSHBUTTON "&Entfernen", IDC_ACELIST_REMOVE, 170, 87, 50, 14
- LTEXT "Erlauben", -1, 135, 107, 32, 8, SS_CENTER
- LTEXT "Verbieten", -1, 176, 107, 32, 8, SS_CENTER
+ LTEXT "Erlauben", IDC_LABEL_ALLOW, 135, 107, 32, 8, SS_CENTER
+ LTEXT "Verbieten", IDC_LABEL_DENY, 176, 107, 32, 8, SS_CENTER
+ CONTROL "", IDC_ACE_CHECKLIST, "CHECKLIST_ACLUI", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 117, 213, 72, WS_EX_CLIENTEDGE
END
STRINGTABLE DISCARDABLE
--- trunk/reactos/lib/aclui/aclui_En.rc 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/aclui_En.rc 2005-07-01 23:33:34 UTC (rev 16374)
@@ -1,7 +1,7 @@
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
IDD_SECPAGE DIALOGEX 0, 0, 227, 215
-STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION
+STYLE DS_NOFAILCREATE | DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CAPTION
CAPTION "Security"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
@@ -9,8 +9,9 @@
CONTROL "", IDC_ACELIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 7, 17, 213, 66, WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE
PUSHBUTTON "A&dd...", IDC_ACELIST_ADD, 116, 87, 50, 14
PUSHBUTTON "&Remove", IDC_ACELIST_REMOVE, 170, 87, 50, 14
- LTEXT "Allow", -1, 135, 107, 32, 8, SS_CENTER
- LTEXT "Deny", -1, 176, 107, 32, 8, SS_CENTER
+ LTEXT "Allow", IDC_LABEL_ALLOW, 135, 107, 32, 8, SS_CENTER
+ LTEXT "Deny", IDC_LABEL_DENY, 176, 107, 32, 8, SS_CENTER
+ CONTROL "", IDC_ACE_CHECKLIST, "CHECKLIST_ACLUI", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 117, 213, 72, WS_EX_CLIENTEDGE
END
STRINGTABLE DISCARDABLE
--- trunk/reactos/lib/aclui/aclui_Sv.rc 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/aclui_Sv.rc 2005-07-01 23:33:34 UTC (rev 16374)
@@ -19,7 +19,7 @@
LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT
IDD_SECPAGE DIALOGEX 0, 0, 227, 215
-STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION
+STYLE DS_NOFAILCREATE | DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CAPTION
CAPTION "Sõkerhet"
FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
@@ -27,8 +27,9 @@
CONTROL "", IDC_ACELIST, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 7, 17, 213, 66, WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE
PUSHBUTTON "&Lõgg till...", IDC_ACELIST_ADD, 116, 87, 50, 14
PUSHBUTTON "&Ta bort", IDC_ACELIST_REMOVE, 170, 87, 50, 14
- LTEXT "TillÕt", -1, 135, 107, 32, 8, SS_CENTER
- LTEXT "Neka", -1, 176, 107, 32, 8, SS_CENTER
+ LTEXT "TillÕt", IDC_LABEL_ALLOW, 135, 107, 32, 8, SS_CENTER
+ LTEXT "Neka", IDC_LABEL_DENY, 176, 107, 32, 8, SS_CENTER
+ CONTROL "", IDC_ACE_CHECKLIST, "CHECKLIST_ACLUI", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 117, 213, 72, WS_EX_CLIENTEDGE
END
STRINGTABLE DISCARDABLE
--- trunk/reactos/lib/aclui/acluilib.h 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/acluilib.h 2005-07-01 23:33:34 UTC (rev 16374)
@@ -33,6 +33,8 @@
typedef struct _SECURITY_PAGE
{
HWND hWnd;
+ HWND hBtnRemove;
+ HWND hAceCheckList;
/* Main ACE List */
HWND hWndAceList;
@@ -44,6 +46,8 @@
SI_OBJECT_INFO ObjectInfo;
} SECURITY_PAGE, *PSECURITY_PAGE;
+/* MISC ***********************************************************************/
+
BOOL
OpenLSAPolicyHandle(IN WCHAR *SystemName,
IN ACCESS_MASK DesiredAccess,
@@ -55,4 +59,36 @@
OUT LPWSTR *lpTarget,
...);
+LPARAM
+ListViewGetSelectedItemData(IN HWND hwnd);
+
+BOOL
+ListViewSelectItem(IN HWND hwnd,
+ IN INT Index);
+
+/* CHECKLIST CONTROL **********************************************************/
+
+#define CIS_DISABLED (0x2)
+#define CIS_ENABLED (0x0)
+#define CIS_ALLOW (0x1)
+#define CIS_DENY (0x0)
+
+#define CLB_ALLOW (0x1)
+#define CLB_DENY (0x0)
+
+#define CIS_MASK (CIS_DISABLED | CIS_ALLOW | CIS_DENY)
+
+#define CLM_ADDITEM (WM_USER + 1)
+#define CLM_DELITEM (WM_USER + 2)
+#define CLM_GETITEMCOUNT (WM_USER + 3)
+#define CLM_CLEAR (WM_USER + 4)
+#define CLM_SETCHECKBOXCOLUMN (WM_USER + 5)
+#define CLM_GETCHECKBOXCOLUMN (WM_USER + 6)
+
+BOOL
+RegisterCheckListControl(HINSTANCE hInstance);
+
+VOID
+UnregisterCheckListControl(VOID);
+
/* EOF */
--- trunk/reactos/lib/aclui/checklist.c 2005-07-01 23:26:01 UTC (rev 16373)
+++ trunk/reactos/lib/aclui/checklist.c 2005-07-01 23:33:34 UTC (rev 16374)
@@ -0,0 +1,785 @@
+/*
+ * ReactOS Access Control List Editor
+ * Copyright (C) 2004 ReactOS Team
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* $Id$
+ *
+ * PROJECT: ReactOS Access Control List Editor
+ * FILE: lib/aclui/checklist.c
+ * PURPOSE: Access Control List Editor
+ * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
+ *
+ * UPDATE HISTORY:
+ * 08/10/2004 Created
+ */
+#include "acluilib.h"
+
+typedef struct _CHECKITEM
+{
+ struct _CHECKITEM *Next;
+ DWORD State;
+ WCHAR Name[1];
+} CHECKITEM, *PCHECKITEM;
+
+typedef struct _CHECKLISTWND
+{
+ HWND hSelf;
+ HWND hNotify;
+ DWORD Style;
+ HFONT hFont;
+
+ PCHECKITEM CheckItemListHead;
+ UINT CheckItemCount;
+
+ INT ItemHeight;
+ BOOL HasFocus;
+
+ COLORREF TextColor[2];
+ UINT CheckBoxLeft[2];
+} CHECKLISTWND, *PCHECKLISTWND;
+
+static PCHECKITEM
+FindCheckItemByIndex(IN PCHECKLISTWND infoPtr,
+ IN UINT Index)
+{
+ PCHECKITEM Item, Found = NULL;
+
+ for (Item = infoPtr->CheckItemListHead;
+ Item != NULL;
+ Item = Item->Next)
+ {
+ if (Index == 0)
+ {
+ Found = Item;
+ break;
+ }
+
+ Index--;
+ }
+
+ return Found;
+}
+
+static VOID
+ClearCheckItems(IN PCHECKLISTWND infoPtr)
+{
+ PCHECKITEM CurItem, NextItem;
+
+ CurItem = infoPtr->CheckItemListHead;
+ while (CurItem != NULL)
+ {
+ NextItem = CurItem->Next;
+ HeapFree(GetProcessHeap(),
+ 0,
+ CurItem);
+ CurItem = NextItem;
+ }
+
+ infoPtr->CheckItemListHead = NULL;
+ infoPtr->CheckItemCount = 0;
+}
+
+static BOOL
+DeleteCheckItem(IN PCHECKLISTWND infoPtr,
+ IN PCHECKITEM Item)
+{
+ PCHECKITEM CurItem;
+ PCHECKITEM *PrevPtr = &infoPtr->CheckItemListHead;
+
+ for (CurItem = infoPtr->CheckItemListHead;
+ CurItem != NULL;
+ CurItem = CurItem->Next)
+ {
+ if (CurItem == Item)
+ {
+ *PrevPtr = CurItem->Next;
+ HeapFree(GetProcessHeap(),
+ 0,
+ CurItem);
+ infoPtr->CheckItemCount--;
+ return TRUE;
+ }
+
+ PrevPtr = &CurItem->Next;
+ }
+
+ return FALSE;
+}
+
+static PCHECKITEM
+AddCheckItem(IN PCHECKLISTWND infoPtr,
+ IN LPWSTR Name,
+ IN DWORD State)
+{
+ PCHECKITEM CurItem;
+ PCHECKITEM *PrevPtr = &infoPtr->CheckItemListHead;
+ PCHECKITEM Item = HeapAlloc(GetProcessHeap(),
+ 0,
+ sizeof(CHECKITEM) + (wcslen(Name) * sizeof(WCHAR)));
+ if (Item != NULL)
+ {
+ for (CurItem = infoPtr->CheckItemListHead;
+ CurItem != NULL;
+ CurItem = CurItem->Next)
+ {
+ PrevPtr = &CurItem->Next;
+ }
+
+ Item->Next = NULL;
+ Item->State = State & CIS_MASK;
+ wcscpy(Item->Name,
+ Name);
+
+ *PrevPtr = Item;
+ infoPtr->CheckItemCount++;
+ }
+
+ return Item;
+}
+
+static VOID
+UpdateControl(IN PCHECKLISTWND infoPtr,
+ IN BOOL AllowChangeStyle)
+{
+ RECT rcClient;
+ SCROLLINFO ScrollInfo;
+
+ GetClientRect(infoPtr->hSelf,
+ &rcClient);
+
+ ScrollInfo.cbSize = sizeof(ScrollInfo);
+ ScrollInfo.fMask = SIF_PAGE | SIF_RANGE;
+ ScrollInfo.nMin = 0;
+ ScrollInfo.nMax = infoPtr->CheckItemCount;
+ ScrollInfo.nPage = ((rcClient.bottom - rcClient.top) + infoPtr->ItemHeight - 1) / infoPtr->ItemHeight;
+ ScrollInfo.nPos = 0;
+ ScrollInfo.nTrackPos = 0;
+
+ if (AllowChangeStyle)
+ {
+ /* determine whether the vertical scrollbar has to be visible or not */
+ if (ScrollInfo.nMax > ScrollInfo.nPage &&
+ !(infoPtr->Style & WS_VSCROLL))
+ {
+ SetWindowLong(infoPtr->hSelf,
+ GWL_STYLE,
+ infoPtr->Style | WS_VSCROLL);
+ }
+ else if (ScrollInfo.nMax < ScrollInfo.nPage &&
+ infoPtr->Style & WS_VSCROLL)
+ {
+ SetWindowLong(infoPtr->hSelf,
+ GWL_STYLE,
+ infoPtr->Style & ~WS_VSCROLL);
+ }
+ }
+
+ SetScrollInfo(infoPtr->hSelf,
+ SB_VERT,
+ &ScrollInfo,
+ TRUE);
+
+ RedrawWindow(infoPtr->hSelf,
+ NULL,
+ NULL,
+ RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN);
+}
+
+static UINT
+GetIdealItemHeight(IN PCHECKLISTWND infoPtr)
+{
+ HDC hdc = GetDC(infoPtr->hSelf);
+ if(hdc != NULL)
+ {
+ UINT height;
+ TEXTMETRIC tm;
+ HGDIOBJ hOldFont = SelectObject(hdc,
+ infoPtr->hFont);
+
+ if(GetTextMetrics(hdc,
+ &tm))
+ {
+ height = tm.tmHeight;
+ }
+ else
+ {
+ height = 0;
+ }
+
+ SelectObject(hdc,
+ hOldFont);
+
+ ReleaseDC(infoPtr->hSelf,
+ hdc);
+
+ return height;
+ }
+ return 0;
+}
+
+static HFONT
+RetChangeControlFont(IN PCHECKLISTWND infoPtr,
+ IN HFONT hFont,
+ IN BOOL Redraw)
+{
+ HFONT hOldFont = infoPtr->hFont;
+ infoPtr->hFont = hFont;
+
+ if (hOldFont != hFont)
+ {
+ infoPtr->ItemHeight = 4 + GetIdealItemHeight(infoPtr);
+ }
+
+ UpdateControl(infoPtr,
+ TRUE);
+
+ return hOldFont;
+}
+
+static VOID
+PaintControl(IN PCHECKLISTWND infoPtr,
+ IN HDC hDC,
+ IN PRECT rcUpdate)
+{
+ INT ScrollPos;
+ PCHECKITEM FirstItem, Item;
+ RECT rcClient;
+ UINT VisibleFirstIndex = rcUpdate->top / infoPtr->ItemHeight;
+ UINT LastTouchedIndex = rcUpdate->bottom / infoPtr->ItemHeight;
+
+ FillRect(hDC,
+ rcUpdate,
+ (HBRUSH)(COLOR_WINDOW + 1));
+
+ GetClientRect(infoPtr->hSelf, &rcClient);
+
+ if (infoPtr->Style & WS_VSCROLL)
+ {
+ ScrollPos = GetScrollPos(infoPtr->hSelf,
+ SB_VERT);
+ }
+ else
+ {
+ ScrollPos = 0;
+ }
+
+ FirstItem = FindCheckItemByIndex(infoPtr,
+ ScrollPos + VisibleFirstIndex);
+ if (FirstItem != NULL)
+ {
+ RECT TextRect, ItemRect;
+ HFONT hOldFont;
+ DWORD CurrentIndex;
+ COLORREF OldTextColor;
+ BOOL Enabled, PrevEnabled;
+ POINT ptOld;
+
+ Enabled = IsWindowEnabled(infoPtr->hSelf);
+ PrevEnabled = Enabled;
+
+ ItemRect.left = 0;
+ ItemRect.right = rcClient.right;
+ ItemRect.top = VisibleFirstIndex * infoPtr->ItemHeight;
+
+ TextRect.left = ItemRect.left + 6;
+ TextRect.right = ItemRect.right - 6;
+ TextRect.top = ItemRect.top + 2;
+
+ MoveToEx(hDC,
+ infoPtr->CheckBoxLeft[CLB_ALLOW],
+ ItemRect.top,
+ &ptOld);
+
+ OldTextColor = SetTextColor(hDC,
+ infoPtr->TextColor[Enabled]);
+
+ hOldFont = SelectObject(hDC,
+ infoPtr->hFont);
+
+ for (Item = FirstItem, CurrentIndex = VisibleFirstIndex;
+ Item != NULL && CurrentIndex <= LastTouchedIndex;
+ Item = Item->Next, CurrentIndex++)
+ {
+ TextRect.bottom = TextRect.top + infoPtr->ItemHeight;
+
+ if (Enabled && PrevEnabled != ((Item->State & CIS_DISABLED) == 0))
+ {
+ PrevEnabled = ((Item->State & CIS_DISABLED) == 0);
+
+ SetTextColor(hDC,
+ infoPtr->TextColor[PrevEnabled]);
+ }
+
+ DrawText(hDC,
+ Item->Name,
+ -1,
+ &TextRect,
+ DT_LEFT | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER);
+
+ MoveToEx(hDC,
+ infoPtr->CheckBoxLeft[CLB_ALLOW],
+ TextRect.top - 6,
+ NULL);
+ LineTo(hDC,
+ infoPtr->CheckBoxLeft[CLB_ALLOW],
+ TextRect.bottom - 6);
+ MoveToEx(hDC,
+ infoPtr->CheckBoxLeft[CLB_DENY],
+ TextRect.top - 6,
+ NULL);
+ LineTo(hDC,
+ infoPtr->CheckBoxLeft[CLB_DENY],
+ TextRect.bottom - 6);
+
+ TextRect.top += infoPtr->ItemHeight;
+ }
+
+ SelectObject(hDC,
+ hOldFont);
+
+ SetTextColor(hDC,
+ OldTextColor);
+
+ MoveToEx(hDC,
+ ptOld.x,
+ ptOld.y,
+ NULL);
+ }
+}
+
+LRESULT CALLBACK
+CheckListWndProc(IN HWND hwnd,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam)
+{
+ PCHECKLISTWND infoPtr;
+ LRESULT Ret;
+
+ infoPtr = (PCHECKLISTWND)GetWindowLongPtr(hwnd,
+ 0);
+
+ if (infoPtr == NULL && uMsg != WM_CREATE)
+ {
+ return DefWindowProc(hwnd,
+ uMsg,
+ wParam,
+ lParam);
+ }
+
+ Ret = 0;
+
+ switch (uMsg)
+ {
+ case WM_PAINT:
+ {
+ HDC hdc;
+ RECT rcUpdate;
+ PAINTSTRUCT ps;
+
+ if (GetUpdateRect(hwnd,
+ &rcUpdate,
+ FALSE))
+ {
+ hdc = (wParam != 0 ? (HDC)wParam : BeginPaint(hwnd, &ps));
+
+ PaintControl(infoPtr,
+ hdc,
+ &rcUpdate);
+
+ if (wParam == 0)
+ {
+ EndPaint(hwnd,
+ &ps);
+ }
+ }
+ break;
+ }
+
+ case WM_VSCROLL:
+ {
+ SCROLLINFO ScrollInfo;
+
+ ScrollInfo.cbSize = sizeof(ScrollInfo);
+ ScrollInfo.fMask = SIF_PAGE | SIF_RANGE | SIF_POS | SIF_TRACKPOS;
+
+ if (GetScrollInfo(hwnd,
+ SB_VERT,
+ &ScrollInfo))
+ {
+ INT OldPos = ScrollInfo.nPos;
+
+ switch (LOWORD(wParam))
+ {
+ case SB_BOTTOM:
+ ScrollInfo.nPos = ScrollInfo.nMax;
+ break;
+
+ case SB_LINEDOWN:
+ if (ScrollInfo.nPos < ScrollInfo.nMax)
+ {
+ ScrollInfo.nPos++;
+ }
+ break;
+
+ case SB_LINEUP:
+ if (ScrollInfo.nPos > 0)
+ {
+ ScrollInfo.nPos--;
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ if (ScrollInfo.nPos + ScrollInfo.nPage <= ScrollInfo.nMax)
+ {
+ ScrollInfo.nPos += ScrollInfo.nPage;
+ }
+ else
+ {
+ ScrollInfo.nPos = ScrollInfo.nMax;
+ }
+ break;
+
+ case SB_PAGEUP:
+ if (ScrollInfo.nPos >= ScrollInfo.nPage)
+ {
+ ScrollInfo.nPos -= ScrollInfo.nPage;
+ }
+ else
+ {
+ ScrollInfo.nPos = 0;
+ }
+ break;
+
+ case SB_THUMBPOSITION:
+ {
+ ScrollInfo.nPos = HIWORD(wParam);
+ break;
+ }
+
+ case SB_THUMBTRACK:
+ {
+ ScrollInfo.nPos = ScrollInfo.nTrackPos;
+ break;
+ }
+
+ case SB_TOP:
+ ScrollInfo.nPos = 0;
+ break;
+ }
+
+ if (OldPos != ScrollInfo.nPos)
+ {
+ ScrollInfo.fMask = SIF_POS;
+
+ ScrollInfo.nPos = SetScrollInfo(hwnd,
+ SB_VERT,
+ &ScrollInfo,
+ TRUE);
+
+ if (OldPos != ScrollInfo.nPos)
+ {
+ ScrollWindowEx(hwnd,
+ 0,
+ (OldPos - ScrollInfo.nPos) * infoPtr->ItemHeight,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+
+ RedrawWindow(hwnd,
+ NULL,
+ NULL,
+ RDW_ERASE | RDW_UPDATENOW | RDW_NOCHILDREN);
+ }
+ }
+ }
+ break;
+ }
+
+ case CLM_ADDITEM:
+ {
+ Ret = (AddCheckItem(infoPtr,
+ (LPWSTR)lParam,
+ (DWORD)wParam) != NULL);
+ if (Ret)
+ {
+ UpdateControl(infoPtr,
+ TRUE);
+ }
+ break;
+ }
+
+ case CLM_DELITEM:
+ {
+ PCHECKITEM Item = FindCheckItemByIndex(infoPtr,
+ wParam);
+ if (Item != NULL)
+ {
+ Ret = DeleteCheckItem(infoPtr,
+ Item);
+ if (Ret)
+ {
+ UpdateControl(infoPtr,
+ TRUE);
+ }
+ }
+ else
+ {
+ Ret = FALSE;
+ }
+ break;
+ }
+
+ case CLM_GETITEMCOUNT:
+ {
+ Ret = infoPtr->CheckItemCount;
+ break;
+ }
+
+ case CLM_CLEAR:
+ {
+ ClearCheckItems(infoPtr);
+ UpdateControl(infoPtr,
+ TRUE);
+ break;
+ }
+
+ case CLM_SETCHECKBOXCOLUMN:
+ {
+ infoPtr->CheckBoxLeft[wParam != CLB_DENY] = (UINT)lParam;
+ Ret = 1;
+ break;
+ }
+
+ case CLM_GETCHECKBOXCOLUMN:
+ {
+ Ret = (LRESULT)infoPtr->CheckBoxLeft[wParam != CLB_DENY];
+ break;
+ }
+
+ case WM_SETFONT:
+ {
+ Ret = (LRESULT)RetChangeControlFont(infoPtr,
+ (HFONT)wParam,
+ (BOOL)lParam);
+ break;
+ }
+
+ case WM_GETFONT:
+ {
+ Ret = (LRESULT)infoPtr->hFont;
[truncated at 1000 lines; 270 more skipped]