From 6f91b6c0fe61728cdd9d97e97e5bfbee03ed881e Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Tue, 20 Feb 2024 02:08:56 +0100 Subject: [PATCH 1/6] [SHELL32] Tweak formatting and logging Some style-improvements I wanted to apply before a planned backport. E.g. The biggest source-file CDefView.cpp in [SHELL32] can be shrinked considerably by stripping some outdated comments from 10 and more years ago, when this class was still non-OOP and named ShellView. Less excessive line-lengths also here and there. In case it is not obvious when reviewing: In the beginning of CDevView.cpp in the declaration-part I just reduced the indentation-level by 4 spaces for a big block. Some shell classes were touched during 0.4.15-dev'ing for fixes like the 'unkown'-typo in 0.4.15-dev-6323-g 3854a5d8e93d2c50153bda26ea378e65cc4241fa for example or missing \n were added to dbgprints like in 0.4.15-dev-4492-g 03422451b3b4a7df96a9e9af5ce7533fd6cb55d9 Touched again here, because I want to port those improvements back, but don't intend to increase the size in older releases. The commit looks big, but does consist solely of trivialities. There is no functional change in this commit, aside the logging ofc. --- dll/win32/shell32/CDefView.cpp | 1047 +++++++---------- dll/win32/shell32/CDefaultContextMenu.cpp | 2 +- dll/win32/shell32/COpenWithMenu.cpp | 4 +- dll/win32/shell32/CShellLink.cpp | 2 +- dll/win32/shell32/dialogs/folder_options.cpp | 2 +- .../shell32/droptargets/CFSDropTarget.cpp | 4 +- .../shell32/folders/CControlPanelFolder.cpp | 3 +- dll/win32/shell32/folders/CDrivesFolder.cpp | 50 +- dll/win32/shell32/folders/CRegFolder.cpp | 2 +- dll/win32/shell32/shellmenu/CStartMenu.cpp | 2 +- dll/win32/shell32/shlfolder.cpp | 3 - 11 files changed, 467 insertions(+), 654 deletions(-) diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index 49ccc18cdea..cc5d1624ff7 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -50,17 +50,17 @@ typedef struct #define SHV_CHANGE_NOTIFY WM_USER + 0x1111 -/* For the context menu of the def view, the id of the items are based on 1 because we need - to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled */ +// For the context menu of the def view, the id of the items are based on 1 because we need +// to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled #define CONTEXT_MENU_BASE_ID 1 -/* Convert client coordinates to listview coordinates */ +// Convert client coordinates to listview coordinates static void ClientToListView(HWND hwndLV, POINT *ppt) { POINT Origin = {}; - /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ + // FIXME: LVM_GETORIGIN is broken. See CORE-17266 if (!ListView_GetOrigin(hwndLV, &Origin)) return; @@ -94,7 +94,6 @@ struct MenuCleanup } }; - class CDefView : public CWindowImpl, public CComObjectRootEx, @@ -107,302 +106,301 @@ class CDefView : public IViewObject, public IServiceProvider { - private: - CComPtr m_pSFParent; - CComPtr m_pSF2Parent; - CComPtr m_pShellFolderViewCB; - CComPtr m_pShellBrowser; - CComPtr m_pCommDlgBrowser; - CComPtr m_pShellFolderViewDual; - CListView m_ListView; - HWND m_hWndParent; - FOLDERSETTINGS m_FolderSettings; - HMENU m_hMenu; /* Handle to the menu bar of the browser */ - HMENU m_hMenuArrangeModes; /* Handle to the popup menu with the arrange modes */ - HMENU m_hMenuViewModes; /* Handle to the popup menu with the view modes */ - HMENU m_hContextMenu; /* Handle to the open context menu */ - BOOL m_bmenuBarInitialized; - UINT m_uState; - UINT m_cidl; - PCUITEMID_CHILD *m_apidl; - PIDLIST_ABSOLUTE m_pidlParent; - LISTVIEW_SORT_INFO m_sortInfo; - ULONG m_hNotify; /* Change notification handle */ - HACCEL m_hAccel; - DWORD m_dwAspects; - DWORD m_dwAdvf; - CComPtr m_pAdvSink; - // for drag and drop - CComPtr m_pSourceDataObject; - CComPtr m_pCurDropTarget; /* The sub-item, which is currently dragged over */ - CComPtr m_pCurDataObject; /* The dragged data-object */ - LONG m_iDragOverItem; /* Dragged over item's index, iff m_pCurDropTarget != NULL */ - UINT m_cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ - POINT m_ptLastMousePos; /* Mouse position at last DragOver call */ - POINT m_ptFirstMousePos; /* Mouse position when the drag operation started */ - DWORD m_grfKeyState; - // - CComPtr m_pCM; - CComPtr m_pFileMenu; - - BOOL m_isEditing; - BOOL m_isParentFolderSpecial; - - CLSID m_Category; - BOOL m_Destroyed; - SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data; - - HICON m_hMyComputerIcon; - - private: - HRESULT _MergeToolbar(); - BOOL _Sort(); - HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam); - HRESULT _GetSnapToGrid(); - void _MoveSelectionOnAutoArrange(POINT pt); - INT _FindInsertableIndexFromPoint(POINT pt); - void _HandleStatusBarResize(int width); - void _ForceStatusBarResize(); - void _DoCopyToMoveToFolder(BOOL bCopy); - - public: - CDefView(); - ~CDefView(); - HRESULT WINAPI Initialize(IShellFolder *shellFolder); - HRESULT IncludeObject(PCUITEMID_CHILD pidl); - HRESULT OnDefaultCommand(); - HRESULT OnStateChange(UINT uFlags); - void UpdateStatusbar(); - void CheckToolbar(); - BOOL CreateList(); - void UpdateListColors(); - BOOL InitList(); - static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); - - PCUITEMID_CHILD _PidlByItem(int i); - PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem); - int LV_FindItemByPidl(PCUITEMID_CHILD pidl); - int LV_AddItem(PCUITEMID_CHILD pidl); - BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl); - BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew); - BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl); - static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); - HRESULT FillList(); - HRESULT FillFileMenu(); - HRESULT FillEditMenu(); - HRESULT FillViewMenu(); - HRESULT FillArrangeAsMenu(HMENU hmenuArrange); - HRESULT CheckViewMode(HMENU hmenuView); - UINT GetSelections(); - HRESULT OpenSelectedItems(); - void OnDeactivate(); - void DoActivate(UINT uState); - HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); - HRESULT InvokeContextMenuCommand(CComPtr& pCM, LPCSTR lpVerb, POINT* pt = NULL); - LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection); - - // *** IOleWindow methods *** - virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); - virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); - - // *** IShellView methods *** - virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg); - virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable); - virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState); - virtual HRESULT STDMETHODCALLTYPE Refresh(); - virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd); - virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow(); - virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs); - virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam); - virtual HRESULT STDMETHODCALLTYPE SaveViewState(); - virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags); - virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv); - - // *** IShellView2 methods *** - virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type); - virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params); - virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl); - virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point); - - // *** IShellView3 methods *** - virtual HRESULT STDMETHODCALLTYPE CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd); - - // *** IFolderView methods *** - virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode); - virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode); - virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv); - virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, PITEMID_CHILD *ppidl); - virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems); - virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv); - virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem); - virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem); - virtual HRESULT STDMETHODCALLTYPE GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt); - virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt); - virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt); - virtual HRESULT STDMETHODCALLTYPE GetAutoArrange(); - virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags); - virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags); - - // *** IShellFolderView methods *** - virtual HRESULT STDMETHODCALLTYPE Rearrange(LPARAM sort); - virtual HRESULT STDMETHODCALLTYPE GetArrangeParam(LPARAM *sort); - virtual HRESULT STDMETHODCALLTYPE ArrangeGrid(); - virtual HRESULT STDMETHODCALLTYPE AutoArrange(); - virtual HRESULT STDMETHODCALLTYPE AddObject(PITEMID_CHILD pidl, UINT *item); - virtual HRESULT STDMETHODCALLTYPE GetObject(PITEMID_CHILD *pidl, UINT item); - virtual HRESULT STDMETHODCALLTYPE RemoveObject(PITEMID_CHILD pidl, UINT *item); - virtual HRESULT STDMETHODCALLTYPE GetObjectCount(UINT *count); - virtual HRESULT STDMETHODCALLTYPE SetObjectCount(UINT count, UINT flags); - virtual HRESULT STDMETHODCALLTYPE UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item); - virtual HRESULT STDMETHODCALLTYPE RefreshObject(PITEMID_CHILD pidl, UINT *item); - virtual HRESULT STDMETHODCALLTYPE SetRedraw(BOOL redraw); - virtual HRESULT STDMETHODCALLTYPE GetSelectedCount(UINT *count); - virtual HRESULT STDMETHODCALLTYPE GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items); - virtual HRESULT STDMETHODCALLTYPE IsDropOnSource(IDropTarget *drop_target); - virtual HRESULT STDMETHODCALLTYPE GetDragPoint(POINT *pt); - virtual HRESULT STDMETHODCALLTYPE GetDropPoint(POINT *pt); - virtual HRESULT STDMETHODCALLTYPE MoveIcons(IDataObject *obj); - virtual HRESULT STDMETHODCALLTYPE SetItemPos(PCUITEMID_CHILD pidl, POINT *pt); - virtual HRESULT STDMETHODCALLTYPE IsBkDropTarget(IDropTarget *drop_target); - virtual HRESULT STDMETHODCALLTYPE SetClipboard(BOOL move); - virtual HRESULT STDMETHODCALLTYPE SetPoints(IDataObject *obj); - virtual HRESULT STDMETHODCALLTYPE GetItemSpacing(ITEMSPACING *spacing); - virtual HRESULT STDMETHODCALLTYPE SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb); - virtual HRESULT STDMETHODCALLTYPE Select(UINT flags); - virtual HRESULT STDMETHODCALLTYPE QuerySupport(UINT *support); - virtual HRESULT STDMETHODCALLTYPE SetAutomationObject(IDispatch *disp); - - // *** IOleCommandTarget methods *** - virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); - virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); - - // *** IDropTarget methods *** - virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); - virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); - virtual HRESULT STDMETHODCALLTYPE DragLeave(); - virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); - - // *** IDropSource methods *** - virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState); - virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect); - - // *** IViewObject methods *** - virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, - HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, - BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue); - virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, - DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet); - virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze); - virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze); - virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink); - virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink); - - // *** IServiceProvider methods *** - virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); - - // Message handlers - LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); - - virtual VOID OnFinalMessage(HWND) override; - - static ATL::CWndClassInfo& GetWndClassInfo() - { - static ATL::CWndClassInfo wc = - { - { sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc, - 0, 0, NULL, NULL, - LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"SHELLDLL_DefView", NULL - }, - NULL, NULL, IDC_ARROW, TRUE, 0, _T("") - }; - return wc; - } - - virtual WNDPROC GetWindowProc() +private: + CComPtr m_pSFParent; + CComPtr m_pSF2Parent; + CComPtr m_pShellFolderViewCB; + CComPtr m_pShellBrowser; + CComPtr m_pCommDlgBrowser; + CComPtr m_pShellFolderViewDual; + CListView m_ListView; + HWND m_hWndParent; + FOLDERSETTINGS m_FolderSettings; + HMENU m_hMenu; // Handle to the menu bar of the browser + HMENU m_hMenuArrangeModes; // Handle to the popup menu with the arrange modes + HMENU m_hMenuViewModes; // Handle to the popup menu with the view modes + HMENU m_hContextMenu; // Handle to the open context menu + BOOL m_bmenuBarInitialized; + UINT m_uState; + UINT m_cidl; + PCUITEMID_CHILD *m_apidl; + PIDLIST_ABSOLUTE m_pidlParent; + LISTVIEW_SORT_INFO m_sortInfo; + ULONG m_hNotify; // Change notification handle + HACCEL m_hAccel; + DWORD m_dwAspects; + DWORD m_dwAdvf; + CComPtr m_pAdvSink; + // for drag and drop + CComPtr m_pSourceDataObject; + CComPtr m_pCurDropTarget; // The sub-item, which is currently dragged over + CComPtr m_pCurDataObject; // The dragged data-object + LONG m_iDragOverItem; // Dragged over item's index, if m_pCurDropTarget != NULL + UINT m_cScrollDelay; // Send a WM_*SCROLL msg every 250 ms during drag-scroll + POINT m_ptLastMousePos; // Mouse position at last DragOver call + POINT m_ptFirstMousePos; // Mouse position when the drag operation started + DWORD m_grfKeyState; + // + CComPtr m_pCM; + CComPtr m_pFileMenu; + + BOOL m_isEditing; + BOOL m_isParentFolderSpecial; + + CLSID m_Category; + BOOL m_Destroyed; + SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data; + + HICON m_hMyComputerIcon; + + HRESULT _MergeToolbar(); + BOOL _Sort(); + HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam); + HRESULT _GetSnapToGrid(); + void _MoveSelectionOnAutoArrange(POINT pt); + INT _FindInsertableIndexFromPoint(POINT pt); + void _HandleStatusBarResize(int width); + void _ForceStatusBarResize(); + void _DoCopyToMoveToFolder(BOOL bCopy); + +public: + CDefView(); + ~CDefView(); + HRESULT WINAPI Initialize(IShellFolder *shellFolder); + HRESULT IncludeObject(PCUITEMID_CHILD pidl); + HRESULT OnDefaultCommand(); + HRESULT OnStateChange(UINT uFlags); + void UpdateStatusbar(); + void CheckToolbar(); + BOOL CreateList(); + void UpdateListColors(); + BOOL InitList(); + static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); + + PCUITEMID_CHILD _PidlByItem(int i); + PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem); + int LV_FindItemByPidl(PCUITEMID_CHILD pidl); + int LV_AddItem(PCUITEMID_CHILD pidl); + BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl); + BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew); + BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl); + static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); + HRESULT FillList(); + HRESULT FillFileMenu(); + HRESULT FillEditMenu(); + HRESULT FillViewMenu(); + HRESULT FillArrangeAsMenu(HMENU hmenuArrange); + HRESULT CheckViewMode(HMENU hmenuView); + UINT GetSelections(); + HRESULT OpenSelectedItems(); + void OnDeactivate(); + void DoActivate(UINT uState); + HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + HRESULT InvokeContextMenuCommand(CComPtr& pCM, LPCSTR lpVerb, POINT* pt = NULL); + LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection); + + // *** IOleWindow methods *** + virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); + + // *** IShellView methods *** + virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg); + virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable); + virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState); + virtual HRESULT STDMETHODCALLTYPE Refresh(); + virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd); + virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow(); + virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs); + virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam); + virtual HRESULT STDMETHODCALLTYPE SaveViewState(); + virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags); + virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv); + + // *** IShellView2 methods *** + virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type); + virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params); + virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl); + virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point); + + // *** IShellView3 methods *** + virtual HRESULT STDMETHODCALLTYPE CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd); + + // *** IFolderView methods *** + virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode); + virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode); + virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv); + virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, PITEMID_CHILD *ppidl); + virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems); + virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv); + virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem); + virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem); + virtual HRESULT STDMETHODCALLTYPE GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt); + virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt); + virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt); + virtual HRESULT STDMETHODCALLTYPE GetAutoArrange(); + virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags); + virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags); + + // *** IShellFolderView methods *** + virtual HRESULT STDMETHODCALLTYPE Rearrange(LPARAM sort); + virtual HRESULT STDMETHODCALLTYPE GetArrangeParam(LPARAM *sort); + virtual HRESULT STDMETHODCALLTYPE ArrangeGrid(); + virtual HRESULT STDMETHODCALLTYPE AutoArrange(); + virtual HRESULT STDMETHODCALLTYPE AddObject(PITEMID_CHILD pidl, UINT *item); + virtual HRESULT STDMETHODCALLTYPE GetObject(PITEMID_CHILD *pidl, UINT item); + virtual HRESULT STDMETHODCALLTYPE RemoveObject(PITEMID_CHILD pidl, UINT *item); + virtual HRESULT STDMETHODCALLTYPE GetObjectCount(UINT *count); + virtual HRESULT STDMETHODCALLTYPE SetObjectCount(UINT count, UINT flags); + virtual HRESULT STDMETHODCALLTYPE UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item); + virtual HRESULT STDMETHODCALLTYPE RefreshObject(PITEMID_CHILD pidl, UINT *item); + virtual HRESULT STDMETHODCALLTYPE SetRedraw(BOOL redraw); + virtual HRESULT STDMETHODCALLTYPE GetSelectedCount(UINT *count); + virtual HRESULT STDMETHODCALLTYPE GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items); + virtual HRESULT STDMETHODCALLTYPE IsDropOnSource(IDropTarget *drop_target); + virtual HRESULT STDMETHODCALLTYPE GetDragPoint(POINT *pt); + virtual HRESULT STDMETHODCALLTYPE GetDropPoint(POINT *pt); + virtual HRESULT STDMETHODCALLTYPE MoveIcons(IDataObject *obj); + virtual HRESULT STDMETHODCALLTYPE SetItemPos(PCUITEMID_CHILD pidl, POINT *pt); + virtual HRESULT STDMETHODCALLTYPE IsBkDropTarget(IDropTarget *drop_target); + virtual HRESULT STDMETHODCALLTYPE SetClipboard(BOOL move); + virtual HRESULT STDMETHODCALLTYPE SetPoints(IDataObject *obj); + virtual HRESULT STDMETHODCALLTYPE GetItemSpacing(ITEMSPACING *spacing); + virtual HRESULT STDMETHODCALLTYPE SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb); + virtual HRESULT STDMETHODCALLTYPE Select(UINT flags); + virtual HRESULT STDMETHODCALLTYPE QuerySupport(UINT *support); + virtual HRESULT STDMETHODCALLTYPE SetAutomationObject(IDispatch *disp); + + // *** IOleCommandTarget methods *** + virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText); + virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); + + // *** IDropTarget methods *** + virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT STDMETHODCALLTYPE DragLeave(); + virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); + + // *** IDropSource methods *** + virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState); + virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect); + + // *** IViewObject methods *** + virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, + HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, + BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue); + virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, + DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet); + virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze); + virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze); + virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink); + virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink); + + // *** IServiceProvider methods *** + virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); + + // Message handlers + LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + + virtual VOID OnFinalMessage(HWND) override; + + static ATL::CWndClassInfo& GetWndClassInfo() + { + static ATL::CWndClassInfo wc = { - return WindowProc; - } - - static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - CDefView *pThis; - LRESULT result; - - // Must hold a reference during message handling - pThis = reinterpret_cast(hWnd); - pThis->AddRef(); - result = CWindowImpl::WindowProc(hWnd, uMsg, wParam, lParam); - pThis->Release(); - return result; - } - - BEGIN_MSG_MAP(CDefView) - MESSAGE_HANDLER(WM_SIZE, OnSize) - MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) - MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) - MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate) - MESSAGE_HANDLER(WM_CREATE, OnCreate) - MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) - MESSAGE_HANDLER(WM_NOTIFY, OnNotify) - MESSAGE_HANDLER(WM_COMMAND, OnCommand) - MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify) - MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) - MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem) - MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem) - MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow) - MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) - MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient) - MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange) - MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) - MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) - END_MSG_MAP() - - BEGIN_COM_MAP(CDefView) - // Windows returns E_NOINTERFACE for IOleWindow - // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) - COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView) - COM_INTERFACE_ENTRY_IID(IID_CDefView, IShellView) - COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2) - COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView) - COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView) - COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) - COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) - COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource) - COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject) - COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) - END_COM_MAP() + { sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc, + 0, 0, NULL, NULL, + LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"SHELLDLL_DefView", NULL + }, + NULL, NULL, IDC_ARROW, TRUE, 0, _T("") + }; + return wc; + } + + virtual WNDPROC GetWindowProc() + { + return WindowProc; + } + + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CDefView *pThis; + LRESULT result; + + // Must hold a reference during message handling + pThis = reinterpret_cast(hWnd); + pThis->AddRef(); + result = CWindowImpl::WindowProc(hWnd, uMsg, wParam, lParam); + pThis->Release(); + return result; + } + + BEGIN_MSG_MAP(CDefView) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) + MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) + MESSAGE_HANDLER(WM_NOTIFY, OnNotify) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify) + MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) + MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem) + MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem) + MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow) + MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient) + MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange) + MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) + END_MSG_MAP() + + BEGIN_COM_MAP(CDefView) + // Windows returns E_NOINTERFACE for IOleWindow + // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) + COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView) + COM_INTERFACE_ENTRY_IID(IID_CDefView, IShellView) + COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2) + COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView) + COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) + COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource) + COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject) + COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) + END_COM_MAP() }; -/*menu items */ +// menu items #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500) #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501) #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502) #define ID_LISTVIEW 1 -/*windowsx.h */ +// windowsx.h #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp) #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp) #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp) @@ -470,10 +468,8 @@ HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder) return S_OK; } -/********************************************************** - * - * ##### helperfunctions for communication with ICommDlgBrowser ##### - */ +// ##### helperfunctions for communication with ICommDlgBrowser ##### + HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl) { HRESULT ret = S_OK; @@ -564,7 +560,7 @@ void CDefView::UpdateStatusbar() LRESULT lResult; m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szPartText, &lResult); - /* Don't bother with the extra processing if we only have one StatusBar part. */ + // Don't bother with the extra processing if we only have one StatusBar part if (!m_isParentFolderSpecial) { DWORD uTotalFileSize = 0; @@ -573,7 +569,7 @@ void CDefView::UpdateStatusbar() INT nItem = -1; bool bIsOnlyFoldersSelected = true; - /* If we have something selected then only count selected file sizes. */ + // If we have something selected then only count selected file sizes if (cSelectedItems) { uFileFlags = LVNI_SELECTED; @@ -591,8 +587,8 @@ void CDefView::UpdateStatusbar() } } - /* Don't show the file size text if there is 0 bytes in the folder - * OR we only have folders selected. */ + // Don't show the file size text if there is 0 bytes in the folder + // OR we only have folders selected if ((cSelectedItems && !bIsOnlyFoldersSelected) || uTotalFileSize) { StrFormatByteSizeW(uTotalFileSize, szPartText, _countof(szPartText)); @@ -604,7 +600,7 @@ void CDefView::UpdateStatusbar() m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 1, (LPARAM)szPartText, &lResult); - /* If we are in a Recycle Bin folder then show no text for the location part. */ + // If we are in a Recycle Bin then show no text for the location part if (!_ILIsBitBucket(m_pidlParent)) { LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText, _countof(szPartText)); @@ -616,16 +612,10 @@ void CDefView::UpdateStatusbar() } } -/********************************************************** - * - * ##### helperfunctions for initializing the view ##### - */ -/********************************************************** -* ShellView_CreateList() -* -* - creates the list view window -*/ +// ##### helperfunctions for initializing the view ##### + +// creates the list view window BOOL CDefView::CreateList() { HRESULT hr; @@ -646,7 +636,7 @@ BOOL CDefView::CreateList() } else { - dwStyle |= LVS_SHOWSELALWAYS; // MSDN says FWF_SHOWSELALWAYS is deprecated, always turn on for folders. + dwStyle |= LVS_SHOWSELALWAYS; // MSDN says FWF_SHOWSELALWAYS is deprecated, always turn on for folders dwStyle |= (m_FolderSettings.fFlags & FWF_ALIGNLEFT) ? LVS_ALIGNLEFT : LVS_ALIGNTOP; ListExStyle = LVS_EX_DOUBLEBUFFER; } @@ -666,19 +656,15 @@ BOOL CDefView::CreateList() case FVM_ICON: dwStyle |= LVS_ICON; break; - case FVM_DETAILS: dwStyle |= LVS_REPORT; break; - case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break; - case FVM_LIST: dwStyle |= LVS_LIST; break; - default: dwStyle |= LVS_LIST; break; @@ -704,7 +690,7 @@ BOOL CDefView::CreateList() #if 0 // FIXME: Because this is a negative, everyone gets the new flag by default unless they - // opt out. This code should be enabled when the shell looks like Vista instead of 2003. + // opt out. This code should be enabled when shell looks like Vista instead of 2003 if (!(m_FolderSettings.fFlags & FWF_NOHEADERINALLVIEWS)) ListExStyle |= LVS_EX_HEADERINALLVIEWS; #endif @@ -779,16 +765,12 @@ void CDefView::UpdateListColors() m_ListView.SetTextColor(clrText); - // Background is painted by the parent via WM_PRINTCLIENT. + // Background is painted by the parent via WM_PRINTCLIENT m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND); } } -/********************************************************** -* ShellView_InitList() -* -* - adds all needed columns to the shellview -*/ +// adds all needed columns to the shellview BOOL CDefView::InitList() { SHELLDETAILS sd; @@ -869,7 +851,7 @@ BOOL CDefView::_Sort() hHeader = (HWND)m_ListView.SendMessage(LVM_GETHEADER, 0, 0); ZeroMemory(&hColumn, sizeof(hColumn)); - /* If the sorting column changed, remove the sorting style from the old column */ + // If the sorting column changed, remove sorting style from the old column if ( (m_sortInfo.nLastHeaderID != -1) && (m_sortInfo.nLastHeaderID != m_sortInfo.nHeaderID) ) { @@ -906,9 +888,6 @@ PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem) return reinterpret_cast(lvItem.lParam); } -/********************************************************** -* LV_FindItemByPidl() -*/ int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl) { ASSERT(m_ListView); @@ -924,9 +903,6 @@ int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl) return -1; } -/********************************************************** -* LV_AddItem() -*/ int CDefView::LV_AddItem(PCUITEMID_CHILD pidl) { LVITEMW lvItem; @@ -938,20 +914,17 @@ int CDefView::LV_AddItem(PCUITEMID_CHILD pidl) if (_DoFolderViewCB(SFVM_ADDINGOBJECT, 0, (LPARAM)pidl) == S_FALSE) return -1; - lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ - lvItem.iItem = m_ListView.GetItemCount(); /*add the item to the end of the list*/ + lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; // set mask + lvItem.iItem = m_ListView.GetItemCount(); // add item to lists end lvItem.iSubItem = 0; - lvItem.lParam = reinterpret_cast(ILClone(pidl)); /*set the item's data*/ - lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/ - lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ + lvItem.lParam = reinterpret_cast(ILClone(pidl)); // set item's data + lvItem.pszText = LPSTR_TEXTCALLBACKW; // get text on a callback basis + lvItem.iImage = I_IMAGECALLBACK; // get image on a callback basis lvItem.stateMask = LVIS_CUT; return m_ListView.InsertItem(&lvItem); } -/********************************************************** -* LV_DeleteItem() -*/ BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl) { int nIndex; @@ -967,9 +940,6 @@ BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl) return m_ListView.DeleteItem(nIndex); } -/********************************************************** -* LV_RenameItem() -*/ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew) { int nItem; @@ -981,35 +951,34 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew nItem = LV_FindItemByPidl(pidlOld); - if ( -1 != nItem ) + if (-1 != nItem) { - lvItem.mask = LVIF_PARAM; /* only the pidl */ + lvItem.mask = LVIF_PARAM; // only the pidl lvItem.iItem = nItem; lvItem.iSubItem = 0; m_ListView.GetItem(&lvItem); - LPVOID oldPidl = reinterpret_cast(lvItem.lParam); /* Store the old pidl until the new item is replaced */ + // Store old pidl until new item is replaced + LPVOID oldPidl = reinterpret_cast(lvItem.lParam); lvItem.mask = LVIF_PARAM | LVIF_IMAGE | LVIF_TEXT; lvItem.iItem = nItem; lvItem.iSubItem = 0; - lvItem.lParam = reinterpret_cast(ILClone(pidlNew)); /* set the item's data */ + lvItem.lParam = reinterpret_cast(ILClone(pidlNew)); // set item's data lvItem.pszText = LPSTR_TEXTCALLBACKW; lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); m_ListView.SetItem(&lvItem); m_ListView.Update(nItem); - SHFree(oldPidl); /* Now that the new item is in place, we can safely release the old pidl */ + // Now that the new item is in place, we can safely release the old pidl + SHFree(oldPidl); - return TRUE; /* FIXME: better handling */ + return TRUE; // FIXME: better handling } return FALSE; } -/********************************************************** -* LV_ProdItem() -*/ BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl) { int nItem; @@ -1035,19 +1004,12 @@ BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl) return FALSE; } -/********************************************************** -* ShellView_FillList() -* -* - gets the objectlist from the shellfolder -* - sorts the list -* - fills the list into the view -*/ INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg) { PITEMID_CHILD pidl = static_cast(ptr); CDefView *pThis = static_cast(arg); - /* in a commdlg This works as a filemask*/ + // in a commdlg this works as a filemask if (pThis->IncludeObject(pidl) == S_OK && pThis->m_ListView) pThis->LV_AddItem(pidl); @@ -1055,6 +1017,10 @@ INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg) return TRUE; } +/// +// - gets the objectlist from the shellfolder +// - sorts the list +// - fills the list into the view HRESULT CDefView::FillList() { CComPtr pEnumIDList; @@ -1067,7 +1033,7 @@ HRESULT CDefView::FillList() TRACE("%p\n", this); - /* determine if there is a setting to show all the hidden files/folders */ + // determine if there is a setting to show all the hidden files/folders dwValue = 1; cbValue = sizeof(dwValue); SHGetValueW(HKEY_CURRENT_USER, @@ -1090,7 +1056,7 @@ HRESULT CDefView::FillList() m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0); } - /* get the itemlist from the shfolder */ + // get the itemlist from the shfolder hRes = m_pSFParent->EnumObjects(m_hWnd, dFlags, &pEnumIDList); if (hRes != S_OK) { @@ -1099,14 +1065,12 @@ HRESULT CDefView::FillList() return(hRes); } - /* create a pointer array */ + // create a pointer array hdpa = DPA_Create(16); if (!hdpa) - { return(E_OUTOFMEMORY); - } - /* copy the items into the array*/ + // copy the items into the array while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched) { if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) @@ -1115,7 +1079,7 @@ HRESULT CDefView::FillList() } } - /*turn the listview's redrawing off*/ + // turn listview's redrawing off m_ListView.SetRedraw(FALSE); DPA_DestroyCallback( hdpa, fill_list, this); @@ -1142,7 +1106,7 @@ HRESULT CDefView::FillList() m_viewinfo_data.cbSize = sizeof(m_viewinfo_data); _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data); - /*turn the listview's redrawing back on and force it to draw*/ + // turn listview's redrawing back on and force it to draw m_ListView.SetRedraw(TRUE); UpdateListColors(); @@ -1276,9 +1240,6 @@ VOID CDefView::OnFinalMessage(HWND) this->Release(); } -/********************************************************** -* ShellView_OnCreate() -*/ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { CComPtr pdt; @@ -1289,7 +1250,7 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt)))) { if (FAILED(RegisterDragDrop(m_hWnd, pdt))) - ERR("Registering Drag Drop Failed\n"); + ERR("Error Registering DragDrop\n"); } /* register for receiving notifications */ @@ -1323,22 +1284,22 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, ntreg); - /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */ + //_DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW)); BOOL bPreviousParentSpecial = m_isParentFolderSpecial; - /* A folder is special if it is the Desktop folder, - * a network folder, or a Control Panel folder. */ - m_isParentFolderSpecial = _ILIsDesktop(m_pidlParent) || _ILIsNetHood(m_pidlParent) + // A folder is special if it is the Desktop folder, + // a network folder, or a Control Panel folder + m_isParentFolderSpecial = _ILIsDesktop(m_pidlParent) || _ILIsNetHood(m_pidlParent) || _ILIsControlPanel(ILFindLastID(m_pidlParent)); - /* Only force StatusBar part refresh if the state - * changed from the previous folder. */ + // Only force StatusBar part refresh if the state + // changed from the previous folder if (bPreviousParentSpecial != m_isParentFolderSpecial) { - /* This handles changing StatusBar parts. */ + // This handles changing StatusBar parts _ForceStatusBarResize(); } @@ -1347,9 +1308,7 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl return S_OK; } -/********************************************************** - * #### Handling of the menus #### - */ +// #### Handling of the menus #### extern "C" DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID); @@ -1362,8 +1321,8 @@ HMENU GetSubmenuByID(HMENU hmenu, UINT id) return NULL; } -/* ReallyGetMenuItemID returns the id of an item even if it opens a submenu, - GetMenuItemID returns -1 if the specified item opens a submenu */ +// ReallyGetMenuItemID returns the id of an item even if it opens a submenu, +// GetMenuItemID returns -1 if the specified item opens a submenu UINT ReallyGetMenuItemID(HMENU hmenu, int i) { MENUITEMINFOW mii = {sizeof(mii), MIIM_ID}; @@ -1387,13 +1346,13 @@ HRESULT CDefView::FillFileMenu() DeleteMenu(hFileMenu, i, MF_BYPOSITION); } - /* In case we still have this left over, clean it up! */ + // In case we still have this left over, clean it up if (m_pFileMenu) { IUnknown_SetSite(m_pFileMenu, NULL); m_pFileMenu.Release(); } - /* Store the context menu in m_pFileMenu and keep it in order to invoke the selected command later on */ + // Store context menu in m_pFileMenu and keep it to invoke the selected command later on HRESULT hr = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pFileMenu)); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -1482,7 +1441,6 @@ HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange) CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_UNCHECKED); } - return S_OK; } @@ -1499,14 +1457,11 @@ HRESULT CDefView::CheckViewMode(HMENU hmenuView) return S_OK; } -/********************************************************** -* ShellView_GetSelections() -* -* - fills the m_apidl list with the selected objects -* -* RETURNS -* number of selected items -*/ +/// +// - fills the m_apidl list with the selected objects +// +// RETURNS +// number of selected items UINT CDefView::GetSelections() { SHFree(m_apidl); @@ -1559,7 +1514,7 @@ HRESULT CDefView::InvokeContextMenuCommand(CComPtr& pCM, LPCSTR lp } HRESULT hr = pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&cmi); - // Most of our callers will do this, but in case they don't do that (File menu!) + // Most of our callers will do this, but if they would forget (File menu!) IUnknown_SetSite(pCM, NULL); pCM.Release(); @@ -1569,9 +1524,6 @@ HRESULT CDefView::InvokeContextMenuCommand(CComPtr& pCM, LPCSTR lp return S_OK; } -/********************************************************** - * ShellView_OpenSelectedItems() - */ HRESULT CDefView::OpenSelectedItems() { HMENU hMenu; @@ -1612,9 +1564,6 @@ HRESULT CDefView::OpenSelectedItems() return hResult; } -/********************************************************** - * ShellView_DoContextMenu() - */ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { POINT pt; @@ -1625,7 +1574,7 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b if (m_hContextMenu != NULL) { - ERR("HACK: Aborting context menu in nested call!\n"); + ERR("HACK: Aborting context menu in nested call\n"); return 0; } @@ -1633,7 +1582,7 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b if (!m_hContextMenu) return E_FAIL; - if (lParam != ~0) // unless app key (menu key) was pressed + if (lParam != ~0) // unless app key (menu key) was pressed { pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); @@ -1652,18 +1601,18 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b } m_cidl = m_ListView.GetSelectedCount(); - /* In case we still have this left over, clean it up! */ - hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); + // In case we still have this left over, clean it up + hResult = GetItemObject(m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); MenuCleanup _(m_pCM, m_hContextMenu); if (FAILED_UNEXPECTEDLY(hResult)) return 0; - /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */ + // Use 1 as the first id we want. 0 means that user canceled the menu hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL); if (FAILED_UNEXPECTEDLY(hResult)) return 0; - /* There is no position requested, so try to find one */ + // There is no position requested, so try to find one if (lParam == ~0) { HWND hFocus = ::GetFocus(); @@ -1671,17 +1620,17 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus)) { - /* Is there an item focused and selected? */ + // Is there an item focused and selected? lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED|LVIS_FOCUSED); - /* If not, find the first selected item */ + // If not, find the first selected item if (lvIndex < 0) lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED); } - /* We got something */ + // We got something if (lvIndex > -1) { - /* Let's find the center of the icon */ + // Find the center of the icon RECT rc = { LVIR_ICON }; m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc); pt.x = (rc.right + rc.left) / 2; @@ -1689,14 +1638,14 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b } else { - /* We have to drop it somewhere.. */ + // We have to drop it somewhere pt.x = pt.y = 0; } m_ListView.ClientToScreen(&pt); } - // This runs the message loop, calling back to us with f.e. WM_INITPOPUP (hence why m_hContextMenu and m_pCM exist) + // This runs the message loop, calling back to us with f.e. WM_INITPOPUP (hence why m_hContextMenu and m_pCM exist) uCommand = TrackPopupMenu(m_hContextMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, 0, m_hWnd, NULL); @@ -1717,7 +1666,7 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) HMENU hMenu = NULL; CComPtr pCM; - hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &pCM)); + hResult = GetItemObject(bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &pCM)); if (FAILED_UNEXPECTEDLY(hResult)) return 0; @@ -1736,7 +1685,7 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) if (bUseSelection) { - // FIXME: we should cache this.... + // FIXME: we should cache this SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER; hResult = m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &rfg); if (FAILED_UNEXPECTEDLY(hResult)) @@ -1759,13 +1708,8 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) return 0; } -/********************************************************** - * ##### message handling ##### - */ +// ##### message handling ##### -/********************************************************** -* ShellView_OnSize() -*/ LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { WORD wWidth, wHeight; @@ -1790,12 +1734,7 @@ LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled return 0; } -/********************************************************** -* ShellView_OnDeactivate() -* -* NOTES -* internal -*/ +// internal void CDefView::OnDeactivate() { TRACE("%p\n", this); @@ -1803,7 +1742,6 @@ void CDefView::OnDeactivate() if (m_uState != SVUIA_DEACTIVATE) { // TODO: cleanup menu after deactivation - m_uState = SVUIA_DEACTIVATE; } } @@ -1812,7 +1750,7 @@ void CDefView::DoActivate(UINT uState) { TRACE("%p uState=%x\n", this, uState); - /*don't do anything if the state isn't really changing */ + // don't do anything if the state isn't really changing if (m_uState == uState) { return; @@ -1865,19 +1803,12 @@ void CDefView::_DoCopyToMoveToFolder(BOOL bCopy) InvokeContextMenuCommand(pCM, (bCopy ? "copyto" : "moveto"), NULL); } -/********************************************************** -* ShellView_OnActivate() -*/ LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { DoActivate(SVUIA_ACTIVATE_FOCUS); return 0; } -/********************************************************** -* ShellView_OnSetFocus() -* -*/ LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { TRACE("%p\n", this); @@ -1898,9 +1829,6 @@ LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHan return 0; } -/********************************************************** -* ShellView_OnKillFocus() -*/ LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { TRACE("(%p) stub\n", this); @@ -1912,12 +1840,7 @@ LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHa return 0; } -/********************************************************** -* ShellView_OnCommand() -* -* NOTES -* the CmdID's are the ones from the context menu -*/ +// the CmdID's are the ones from the context menu LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { DWORD dwCmdID; @@ -1938,25 +1861,21 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); CheckToolbar(); break; - case FCIDM_SHVIEW_BIGICON: m_FolderSettings.ViewMode = FVM_ICON; m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON); CheckToolbar(); break; - case FCIDM_SHVIEW_LISTVIEW: m_FolderSettings.ViewMode = FVM_LIST; m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST); CheckToolbar(); break; - case FCIDM_SHVIEW_REPORTVIEW: m_FolderSettings.ViewMode = FVM_DETAILS; m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); CheckToolbar(); break; - /* the menu-ID's for sorting are 0x30... see shrec.rc */ case 0x30: case 0x31: @@ -1966,7 +1885,6 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand m_sortInfo.bIsAscending = TRUE; _Sort(); break; - case FCIDM_SHVIEW_SNAPTOGRID: m_ListView.Arrange(LVA_SNAPTOGRID); break; @@ -1985,17 +1903,14 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand case FCIDM_SHVIEW_SELECTALL: m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED); break; - case FCIDM_SHVIEW_INVERTSELECTION: nCount = m_ListView.GetItemCount(); for (int i=0; i < nCount; i++) m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED); break; - case FCIDM_SHVIEW_REFRESH: Refresh(); break; - case FCIDM_SHVIEW_DELETE: case FCIDM_SHVIEW_CUT: case FCIDM_SHVIEW_COPY: @@ -2003,29 +1918,24 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand case FCIDM_SHVIEW_PROPERTIES: if (SHRestricted(REST_NOVIEWCONTEXTMENU)) return 0; - return OnExplorerCommand(dwCmdID, TRUE); - case FCIDM_SHVIEW_COPYTO: case FCIDM_SHVIEW_MOVETO: _DoCopyToMoveToFolder(dwCmdID == FCIDM_SHVIEW_COPYTO); return 0; - case FCIDM_SHVIEW_INSERT: case FCIDM_SHVIEW_UNDO: case FCIDM_SHVIEW_INSERTLINK: case FCIDM_SHVIEW_NEWFOLDER: return OnExplorerCommand(dwCmdID, FALSE); default: - { - /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pFileMenu handle the command */ + // WM_COMMAND messages from file menu are routed to CDefView to let m_pFileMenu handle them if (m_pFileMenu && dwCmd == 0) { HMENU Dummy = NULL; MenuCleanup _(m_pFileMenu, Dummy); InvokeContextMenuCommand(m_pFileMenu, MAKEINTRESOURCEA(dwCmdID), NULL); } - } } return 0; @@ -2051,18 +1961,14 @@ SelectExtOnRename(void) return !!dwValue; } -/********************************************************** -* ShellView_OnNotify() -*/ - LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { - UINT CtlID; - LPNMHDR lpnmh; - LPNMLISTVIEW lpnmlv; - NMLVDISPINFOW *lpdi; - PCUITEMID_CHILD pidl; - BOOL unused; + UINT CtlID; + LPNMHDR lpnmh; + LPNMLISTVIEW lpnmlv; + NMLVDISPINFOW *lpdi; + PCUITEMID_CHILD pidl; + BOOL unused; CtlID = wParam; lpnmh = (LPNMHDR)lParam; @@ -2077,67 +1983,52 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl TRACE("-- NM_SETFOCUS %p\n", this); OnSetFocus(0, 0, 0, unused); break; - case NM_KILLFOCUS: TRACE("-- NM_KILLFOCUS %p\n", this); OnDeactivate(); /* Notify the ICommDlgBrowser interface */ OnStateChange(CDBOSC_KILLFOCUS); break; - case NM_CUSTOMDRAW: TRACE("-- NM_CUSTOMDRAW %p\n", this); return CDRF_DODEFAULT; - case NM_RELEASEDCAPTURE: TRACE("-- NM_RELEASEDCAPTURE %p\n", this); break; - case NM_CLICK: TRACE("-- NM_CLICK %p\n", this); break; - case NM_RCLICK: TRACE("-- NM_RCLICK %p\n", this); break; - case NM_DBLCLK: TRACE("-- NM_DBLCLK %p\n", this); OpenSelectedItems(); break; - case NM_RETURN: TRACE("-- NM_RETURN %p\n", this); OpenSelectedItems(); break; - case HDN_ENDTRACKW: TRACE("-- HDN_ENDTRACKW %p\n", this); - /*nColumn1 = m_ListView.GetColumnWidth(0); - nColumn2 = m_ListView.GetColumnWidth(1);*/ + //nColumn1 = m_ListView.GetColumnWidth(0); + //nColumn2 = m_ListView.GetColumnWidth(1); break; - case LVN_DELETEITEM: TRACE("-- LVN_DELETEITEM %p\n", this); - /*delete the pidl because we made a copy of it*/ SHFree(reinterpret_cast(lpnmlv->lParam)); - break; - case LVN_DELETEALLITEMS: TRACE("-- LVN_DELETEALLITEMS %p\n", this); return FALSE; - case LVN_INSERTITEM: TRACE("-- LVN_INSERTITEM (STUB)%p\n", this); break; - case LVN_ITEMACTIVATE: TRACE("-- LVN_ITEMACTIVATE %p\n", this); - OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ + OnStateChange(CDBOSC_SELCHANGE); // browser will get the IDataObject break; - case LVN_COLUMNCLICK: m_sortInfo.nHeaderID = lpnmlv->iSubItem; if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID) @@ -2146,7 +2037,6 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl m_sortInfo.bIsAscending = TRUE; _Sort(); break; - case LVN_GETDISPINFOA: case LVN_GETDISPINFOW: TRACE("-- LVN_GETDISPINFO %p\n", this); @@ -2188,25 +2078,20 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes))) { if (attributes & SFGAO_HIDDEN) - { lpdi->item.state |= LVIS_CUT; - } } } lpdi->item.mask |= LVIF_DI_SETITEM; break; - case LVN_ITEMCHANGED: TRACE("-- LVN_ITEMCHANGED %p\n", this); - OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ + OnStateChange(CDBOSC_SELCHANGE); // browser will get the IDataObject UpdateStatusbar(); _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */); break; - case LVN_BEGINDRAG: case LVN_BEGINRDRAG: TRACE("-- LVN_BEGINDRAG\n"); - if (GetSelections()) { CComPtr pda; @@ -2218,15 +2103,11 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl LPNMLISTVIEW params = (LPNMLISTVIEW)lParam; if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes))) - { dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK); - } CComPtr piaso; if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso)))) - { piaso->SetAsyncMode(TRUE); - } DWORD dwEffect2; @@ -2243,14 +2124,11 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl m_ListView.GetItemPosition(params->iItem, &ptItem); ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y); - DoDragDrop(pda, this, dwEffect, &dwEffect2); - m_pSourceDataObject.Release(); } } break; - case LVN_BEGINLABELEDITW: { DWORD dwAttr = SFGAO_CANRENAME; @@ -2264,7 +2142,7 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl HWND hEdit = reinterpret_cast(m_ListView.SendMessage(LVM_GETEDITCONTROL)); SHLimitInputEdit(hEdit, m_pSFParent); - /* smartass-renaming: See CORE-15242 */ + // smartass-renaming: See CORE-15242 if (!(dwAttr & SFGAO_FOLDER) && (dwAttr & SFGAO_FILESYSTEM) && (lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename()) { @@ -2286,14 +2164,11 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl m_isEditing = TRUE; return FALSE; } - return TRUE; } - case LVN_ENDLABELEDITW: { TRACE("-- LVN_ENDLABELEDITW %p\n", this); - m_isEditing = FALSE; if (lpdi->item.pszText) @@ -2320,7 +2195,6 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl return FALSE; } - default: TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code); break; @@ -2329,12 +2203,10 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl return 0; } -/* - * This is just a quick hack to make the desktop work correctly. - * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that - * a folder should know if it should update upon a change notification. - * It is exported by merged folders at a minimum. - */ +// This is just a quick hack to make the desktop work correctly. +// ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the +// way that a folder should know if it should update upon a change notification. +// It is exported by merged folders at a minimum. static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2) { if (!pidl1 || !pidl2) @@ -2378,12 +2250,9 @@ static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE return FALSE; } -/********************************************************** -* ShellView_OnChange() -*/ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { - // The change notify can come before WM_CREATE. + // The change notify can come before WM_CREATE if (!m_ListView) return FALSE; @@ -2411,22 +2280,16 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & if (bParent0) { if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1) - { LV_AddItem(ILFindLastID(Pidls[0])); - } else - { LV_ProdItem(ILFindLastID(Pidls[0])); - } } break; - case SHCNE_RMDIR: case SHCNE_DELETE: if (bParent0) LV_DeleteItem(ILFindLastID(Pidls[0])); break; - case SHCNE_RENAMEFOLDER: case SHCNE_RENAMEITEM: if (bParent0 && bParent1) @@ -2436,12 +2299,10 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & else if (bParent1) LV_AddItem(ILFindLastID(Pidls[1])); break; - case SHCNE_UPDATEITEM: if (bParent0) LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0])); break; - case SHCNE_UPDATEDIR: Refresh(); break; @@ -2454,20 +2315,17 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId); HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId); -/********************************************************** -* CDefView::OnCustomItem -*/ LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { if (!m_pCM) { /* no menu */ - ERR("no context menu!!!\n"); + ERR("no context menu\n"); return FALSE; } - /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to - be changed to a menu identifier offset */ + // lParam of WM_DRAWITEM WM_MEASUREITEM contains a menu id and + // this also needs to be changed to a menu identifier offset UINT CmdID; HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID); if (SUCCEEDED(hres)) @@ -2489,9 +2347,6 @@ LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL return S_OK; } -/********************************************************** -* CDefView::OnInitMenuPopup -*/ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { HMENU hmenu = (HMENU) wParam; @@ -2499,9 +2354,7 @@ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL UINT menuItemId; if (m_pCM) - { OnCustomItem(uMsg, wParam, lParam, bHandled); - } HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); @@ -2552,18 +2405,9 @@ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL return FALSE; } -/********************************************************** -* -* -* The INTERFACE of the IShellView object -* -* -********************************************************** -*/ -/********************************************************** -* ShellView_GetWindow -*/ +// The INTERFACE of the IShellView object + HRESULT WINAPI CDefView::GetWindow(HWND *phWnd) { TRACE("(%p)\n", this); @@ -2580,12 +2424,7 @@ HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode) return E_NOTIMPL; } -/********************************************************** -* IShellView_TranslateAccelerator -* -* FIXME: -* use the accel functions -*/ +// FIXME: use the accel functions HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) { if (m_isEditing) @@ -2596,7 +2435,7 @@ HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0) return S_OK; - TRACE("-- key=0x%04lx\n", lpmsg->wParam) ; + TRACE("-- key=0x%04lx\n", lpmsg->wParam); } return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0); @@ -2604,30 +2443,27 @@ HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable) { - FIXME("(%p) stub\n", this); - + FIXME("(%p)\n", this); return E_NOTIMPL; } HRESULT WINAPI CDefView::UIActivate(UINT uState) { - TRACE("(%p)->(state=%x) stub\n", this, uState); + TRACE("(%p)->(state=%x)\n", this, uState); - /* don't do anything if the state isn't really changing */ + // don't do anything if the state isn't changing if (m_uState == uState) - { return S_OK; - } - /* OnActivate handles the menu merging and internal state */ + // OnActivate handles the menu merging and internal state DoActivate(uState); - /* only do This if we are active */ + // only do this if we are active if (uState != SVUIA_DEACTIVATE) { _ForceStatusBarResize(); - /* Set the text for the status bar */ + // Set the text for the status bar UpdateStatusbar(); } @@ -2661,7 +2497,7 @@ HRESULT WINAPI CDefView::DestroyViewWindow() if (m_hAccel) { - // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN + // MSDN: Accelerator tables loaded from resources are freed automatically when application terminates m_hAccel = NULL; } @@ -2815,7 +2651,6 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut) hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut); } break; - case SVGIO_SELECTION: GetSelections(); hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut); @@ -3050,9 +2885,8 @@ HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_ return S_OK; } -/********************************************************** - * IShellView2 implementation - */ + +// IShellView2 implementation HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type) { @@ -3159,9 +2993,8 @@ HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UI return E_NOTIMPL; } -/********************************************************** - * IShellFolderView implementation - */ +// IShellFolderView implementation + HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort) { FIXME("(%p)->(%ld) stub\n", this, sort); @@ -3378,9 +3211,6 @@ HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp) return E_NOTIMPL; } -/********************************************************** - * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) - */ HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) { FIXME("(%p)->(%p(%s) 0x%08x %p %p\n", @@ -3398,11 +3228,10 @@ HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLE return OLECMDERR_E_UNKNOWNGROUP; } -/********************************************************** - * ISVOleCmdTarget_Exec (IOleCommandTarget) - * - * nCmdID is the OLECMDID_* enumeration - */ +/// +// ISVOleCmdTarget_Exec(IOleCommandTarget) +// +// nCmdID is the OLECMDID_* enumeration HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n", @@ -3424,7 +3253,7 @@ HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCm if (m_hMenuViewModes) { - /* Duplicate all but the last two items of the view modes menu */ + // Duplicate all but the last two items of the view modes menu HMENU hmenuViewPopup = CreatePopupMenu(); Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0); DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); @@ -3477,8 +3306,8 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf to remember the last key state when the button was pressed */ m_grfKeyState = grfKeyState; - /* Map from global to client coordinates and query the index of the listview-item, which is - * currently under the mouse cursor. */ + // Map from global to client coordinates and query the index of the + // listview-item, which is currently under the mouse cursor. LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM}; ScreenToClient(&htinfo.pt); lResult = m_ListView.HitTest(&htinfo); @@ -3487,9 +3316,9 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf ::GetClientRect(m_ListView, &clientRect); if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y && (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH || - htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH )) + htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)) { - m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */ + m_cScrollDelay = (m_cScrollDelay + 1) % 5; // DragOver is called every 50 ms if (m_cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */ @@ -3508,7 +3337,7 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf } else { - m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */ + m_cScrollDelay = 0; // Reset, if cursor is not over the listview's scroll-area } m_ptLastMousePos = htinfo.pt; @@ -3530,11 +3359,11 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf } } - /* If we are still over the previous sub-item, notify it via DragOver and return. */ + // If we are still over the previous sub-item, notify it via DragOver and return if (m_pCurDropTarget && lResult == m_iDragOverItem) return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect); - /* We've left the previous sub-item, notify it via DragLeave and Release it. */ + // We've left the previous sub-item, notify it via DragLeave and release it if (m_pCurDropTarget) { PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem); @@ -3549,23 +3378,23 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf if (lResult == -1) { - /* We are not above one of the listview's subitems. Bind to the parent folder's - * DropTarget interface. */ + // We are not above one of the listview's subitems. Bind to the + // parent folder's DropTarget interface. hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget)); } else { - /* Query the relative PIDL of the shellfolder object represented by the currently - * dragged over listview-item ... */ + // Query the relative PIDL of the shellfolder object represented + // by the currently dragged over listview-item ... PCUITEMID_CHILD pidl = _PidlByItem(lResult); - /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */ + // ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget)); } IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this); - /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */ + // If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state if (FAILED(hr)) { *pdwEffect = DROPEFFECT_NONE; @@ -3577,7 +3406,7 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf SelectItem(m_iDragOverItem, SVSI_SELECT); } - /* Notify the item just entered via DragEnter. */ + // Notify the item just entered via DragEnter return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect); } @@ -3636,7 +3465,7 @@ INT CDefView::_FindInsertableIndexFromPoint(POINT pt) INT dx, dy; BOOL bSmall = ((m_ListView.GetStyle() & LVS_TYPEMASK) != LVS_ICON); - /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ + // FIXME: LVM_GETORIGIN is broken. See CORE-17266 pt.x += m_ListView.GetScrollPos(SB_HORZ); pt.y += m_ListView.GetScrollPos(SB_VERT); @@ -3713,28 +3542,28 @@ void CDefView::_HandleStatusBarResize(int nWidth) const int nLocationPartLength = 150; const int nRightPartsLength = nFileSizePartLength + nLocationPartLength; int nObjectsPartLength = nWidth - nRightPartsLength; - - /* If the window is small enough just divide each part into thirds - * This is the behavior of Windows Server 2003. */ + + // If the window is small enough just divide each part into thirds + // to match the behavior of Windows Server 2003 if (nObjectsPartLength <= nLocationPartLength) nObjectsPartLength = nFileSizePartLength = nWidth / 3; int nPartArray[] = {nObjectsPartLength, nObjectsPartLength + nFileSizePartLength, -1}; - + m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, _countof(nPartArray), (LPARAM)nPartArray, &lResult); } void CDefView::_ForceStatusBarResize() { - /* Get the handle for the status bar */ + // Get the handle for the status bar HWND fStatusBar; m_pShellBrowser->GetControlWindow(FCW_STATUS, &fStatusBar); - /* Get the size of our status bar */ + // Get the size of our status bar RECT statusBarSize; ::GetWindowRect(fStatusBar, &statusBarSize); - /* Resize the status bar */ + // Resize the status bar _HandleStatusBarResize(statusBarSize.right - statusBarSize.left); } @@ -3864,10 +3693,6 @@ HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINT return S_OK; } -/********************************************************** - * ISVDropSource implementation - */ - HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) { TRACE("(%p)\n", this); @@ -3887,35 +3712,27 @@ HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect) return DRAGDROP_S_USEDEFAULTCURSORS; } -/********************************************************** - * ISVViewObject implementation - */ - HRESULT WINAPI CDefView::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue) { FIXME("Stub: this=%p\n", this); - return E_NOTIMPL; } HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet) { FIXME("Stub: this=%p\n", this); - return E_NOTIMPL; } HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) { FIXME("Stub: this=%p\n", this); - return E_NOTIMPL; } HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze) { FIXME("Stub: this=%p\n", this); - return E_NOTIMPL; } @@ -3923,7 +3740,7 @@ HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvS { FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink); - /* FIXME: we set the AdviseSink, but never use it to send any advice */ + // FIXME: we set the AdviseSink, but never use it to send any advice m_pAdvSink = pAdvSink; m_dwAspects = aspects; m_dwAdvf = advf; @@ -4005,8 +3822,8 @@ HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppv } HRESULT WINAPI SHCreateShellFolderViewEx( - LPCSFV psvcbi, /* [in] shelltemplate struct */ - IShellView **ppsv) /* [out] IShellView pointer */ + LPCSFV psvcbi, // [in] shelltemplate struct + IShellView **ppsv) // [out] IShellView pointer { CComPtr psv; HRESULT hRes; @@ -4025,7 +3842,7 @@ HRESULT WINAPI SHCreateShellFolderViewEx( } HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, - IShellView **ppsv) + IShellView **ppsv) { CComPtr psv; HRESULT hRes; diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp b/dll/win32/shell32/CDefaultContextMenu.cpp index 72913f36918..4d0f34a47d4 100644 --- a/dll/win32/shell32/CDefaultContextMenu.cpp +++ b/dll/win32/shell32/CDefaultContextMenu.cpp @@ -1193,7 +1193,7 @@ CDefaultContextMenu::TryToBrowse( hr = SHILCombine(m_pidlFolder, pidlChild, &pidl); if (FAILED_UNEXPECTEDLY(hr)) return hr; - + hr = psb->BrowseObject(pidl, wFlags & ~SBSP_RELATIVE); ILFree(pidl); return hr; diff --git a/dll/win32/shell32/COpenWithMenu.cpp b/dll/win32/shell32/COpenWithMenu.cpp index 759f6c41436..feb30a3a091 100644 --- a/dll/win32/shell32/COpenWithMenu.cpp +++ b/dll/win32/shell32/COpenWithMenu.cpp @@ -716,7 +716,7 @@ BOOL COpenWithList::SetDefaultHandler(SApp *pApp, LPCWSTR pwszFilename) /* Create file extension key */ if (RegCreateKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { - ERR("Cannot open ext key\n"); + ERR("Can't open ext key\n"); return FALSE; } @@ -870,7 +870,7 @@ BOOL COpenWithDialog::IsNoOpen(HWND hwnd) return TRUE; else if (dReturnValue == -1) { - ERR("IsNoOpen failed to load the dialog box.\n"); + ERR("IsNoOpen failed to load dialog box\n"); return TRUE; } } diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index bdd1b617082..aa1fbfbaba5 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -2572,7 +2572,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) HRESULT hr = Resolve(lpici->hwnd, 0); if (FAILED(hr)) { - TRACE("failed to resolve component with error 0x%08x\n", hr); + TRACE("failed to resolve component error 0x%08x\n", hr); return hr; } diff --git a/dll/win32/shell32/dialogs/folder_options.cpp b/dll/win32/shell32/dialogs/folder_options.cpp index bad8fc484c8..ea0e4ed4b4b 100644 --- a/dll/win32/shell32/dialogs/folder_options.cpp +++ b/dll/win32/shell32/dialogs/folder_options.cpp @@ -283,7 +283,7 @@ Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) case 1: // show taskbar options dialog - FIXME("notify explorer to show taskbar options dialog\n"); + FIXME("notify explorer to show taskbar options dlg\n"); //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0); break; diff --git a/dll/win32/shell32/droptargets/CFSDropTarget.cpp b/dll/win32/shell32/droptargets/CFSDropTarget.cpp index f480ffa9808..4d9e506f870 100644 --- a/dll/win32/shell32/droptargets/CFSDropTarget.cpp +++ b/dll/win32/shell32/droptargets/CFSDropTarget.cpp @@ -491,7 +491,7 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject, if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) { hr = pDataObject->GetData(&fmt, &medium); - TRACE("CFSTR_SHELLIDLIST.\n"); + TRACE("CFSTR_SHELLIDLIST\n"); if (FAILED(hr)) { ERR("CFSTR_SHELLIDLIST failed\n"); @@ -721,7 +721,7 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject, } else { - ERR("No viable drop format.\n"); + ERR("No viable drop format\n"); hr = E_FAIL; } return hr; diff --git a/dll/win32/shell32/folders/CControlPanelFolder.cpp b/dll/win32/shell32/folders/CControlPanelFolder.cpp index 085b074ee18..7306862f966 100644 --- a/dll/win32/shell32/folders/CControlPanelFolder.cpp +++ b/dll/win32/shell32/folders/CControlPanelFolder.cpp @@ -411,7 +411,7 @@ HRESULT WINAPI CControlPanelFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_A else if (_ILIsSpecialFolder(*apidl)) m_regFolder->GetAttributesOf(1, apidl, rgfInOut); else - ERR("Got an unknown pidl here!\n"); + ERR("Got unknown pidl\n"); apidl++; cidl--; } @@ -448,7 +448,6 @@ HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner, *ppvOut = NULL; if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) { - /* HACK: We should use callbacks from CDefaultContextMenu instead of creating one on our own */ BOOL bHasCpl = FALSE; for (UINT i = 0; i < cidl; i++) diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp b/dll/win32/shell32/folders/CDrivesFolder.cpp index 2293884e9ea..cf76b47392d 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -24,7 +24,7 @@ #include #include -WINE_DEFAULT_DEBUG_CHANNEL (shell); +WINE_DEFAULT_DEBUG_CHANNEL(shell); /* CDrivesFolder should create a CRegFolder to represent the virtual items that exist only in @@ -599,7 +599,7 @@ CDrivesFolder::CDrivesFolder() CDrivesFolder::~CDrivesFolder() { - TRACE ("-- destroying IShellFolder(%p)\n", this); + TRACE("-- destroying IShellFolder(%p)\n", this); SHFree(pidlRoot); } @@ -680,13 +680,13 @@ HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLEST else if (_ILIsSpecialFolder(pidlTemp)) m_regFolder->GetAttributesOf(1, &pidlTemp, pdwAttributes); else - ERR("Got an unknown pidl here!\n"); + ERR("Got unknown pidl\n"); } } *ppidl = pidlTemp; - TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr); + TRACE("(%p)->(-- ret=0x%08x)\n", this, hr); return hr; } @@ -867,7 +867,7 @@ HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVO SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this}; hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); } - TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut); + TRACE("-- (%p)->(interface=%p)\n", this, ppvOut); return hr; } @@ -876,8 +876,8 @@ HRESULT WINAPI CDrivesFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVO */ HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut) { - TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", - this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); + TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", + this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); if (cidl && !apidl) return E_INVALIDARG; @@ -911,7 +911,7 @@ HRESULT WINAPI CDrivesFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY a /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */ *rgfInOut &= ~SFGAO_VALIDATE; - TRACE ("-- result=0x%08x\n", *rgfInOut); + TRACE("-- result=0x%08x\n", *rgfInOut); return S_OK; } @@ -951,8 +951,8 @@ HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner, } else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) { - hr = IDataObject_Constructor (hwndOwner, - pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); + hr = IDataObject_Constructor(hwndOwner, + pidlRoot, apidl, cidl, TRUE, (IDataObject **)&pObj); } else if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID (riid, IID_IExtractIconW)) && (cidl == 1)) { @@ -977,7 +977,7 @@ HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner, hr = E_OUTOFMEMORY; *ppvOut = pObj; - TRACE ("(%p)->hr=0x%08x\n", this, hr); + TRACE("(%p)->hr=0x%08x\n", this, hr); return hr; } @@ -989,7 +989,7 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla LPWSTR pszPath; HRESULT hr = S_OK; - TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet); + TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet); pdump (pidl); if (!strRet) @@ -1029,9 +1029,9 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags; GetVolumeInformationW(wszDrive, pszPath, - MAX_PATH - 7, - &dwVolumeSerialNumber, - &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0); + MAX_PATH - 7, + &dwVolumeSerialNumber, + &dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0); pszPath[MAX_PATH-1] = L'\0'; if (!wcslen(pszPath)) @@ -1062,10 +1062,10 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla } } } - wcscat (pszPath, L" ("); + wcscat(pszPath, L" ("); wszDrive[2] = L'\0'; - wcscat (pszPath, wszDrive); - wcscat (pszPath, L")"); + wcscat(pszPath, wszDrive); + wcscat(pszPath, L")"); } if (SUCCEEDED(hr)) @@ -1111,19 +1111,19 @@ HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid) { - FIXME ("(%p)\n", this); + FIXME("(%p)\n", this); return E_NOTIMPL; } HRESULT WINAPI CDrivesFolder::EnumSearches(IEnumExtraSearch ** ppenum) { - FIXME ("(%p)\n", this); + FIXME("(%p)\n", this); return E_NOTIMPL; } HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG *pDisplay) { - TRACE ("(%p)\n", this); + TRACE("(%p)\n", this); if (pSort) *pSort = 0; @@ -1134,7 +1134,7 @@ HRESULT WINAPI CDrivesFolder::GetDefaultColumn (DWORD dwRes, ULONG *pSort, ULONG HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags) { - TRACE ("(%p)\n", this); + TRACE("(%p)\n", this); if (!pcsFlags || iColumn >= _countof(MyComputerSFHeader)) return E_INVALIDARG; @@ -1144,7 +1144,7 @@ HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, DWORD * pcsFla HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv) { - FIXME ("(%p)\n", this); + FIXME("(%p)\n", this); return E_NOTIMPL; } @@ -1152,7 +1152,7 @@ HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, S { HRESULT hr; - TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd); + TRACE("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd); if (!psd || iColumn >= _countof(MyComputerSFHeader)) return E_INVALIDARG; @@ -1232,7 +1232,7 @@ HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID * pscid) */ HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId) { - TRACE ("(%p)\n", this); + TRACE("(%p)\n", this); if (!lpClassId) return E_POINTER; diff --git a/dll/win32/shell32/folders/CRegFolder.cpp b/dll/win32/shell32/folders/CRegFolder.cpp index 5b2d513569b..6c5c3f7f3cb 100644 --- a/dll/win32/shell32/folders/CRegFolder.cpp +++ b/dll/win32/shell32/folders/CRegFolder.cpp @@ -513,7 +513,7 @@ HRESULT WINAPI CRegFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apid if (_ILIsSpecialFolder(*apidl)) GetGuidItemAttributes(*apidl, rgfInOut); else - ERR("Got an unknown pidl here!\n"); + ERR("Got unknown pidl\n"); apidl++; cidl--; } diff --git a/dll/win32/shell32/shellmenu/CStartMenu.cpp b/dll/win32/shell32/shellmenu/CStartMenu.cpp index 85d61e9f3f7..311b6516124 100644 --- a/dll/win32/shell32/shellmenu/CStartMenu.cpp +++ b/dll/win32/shell32/shellmenu/CStartMenu.cpp @@ -533,7 +533,7 @@ RSHELL_CStartMenu_CreateInstance(REFIID riid, void **ppv) hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidlProgramsAbsolute); if (FAILED_UNEXPECTEDLY(hr)) { - WARN("USER Programs folder not found.\n"); + WARN("USER Programs folder not found\n"); hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_PROGRAMS, &pidlProgramsAbsolute); if (FAILED_UNEXPECTEDLY(hr)) return hr; diff --git a/dll/win32/shell32/shlfolder.cpp b/dll/win32/shell32/shlfolder.cpp index 92dff6c81ef..d4146506038 100644 --- a/dll/win32/shell32/shlfolder.cpp +++ b/dll/win32/shell32/shlfolder.cpp @@ -26,7 +26,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); - /*************************************************************************** * GetNextElement (internal function) * @@ -424,8 +423,6 @@ SHOpenFolderAndSelectItems(PCIDLIST_ABSOLUTE pidlFolder, return E_FAIL; } - - static DWORD WINAPI _ShowPropertiesDialogThread(LPVOID lpParameter) From 6bc40d36f8b3151bbd7057d085a79fcc0bab5db7 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Tue, 20 Feb 2024 14:36:24 +0900 Subject: [PATCH 2/6] [CTFMON][MSCTFIME][MSCTF][MSUTB][CICERO] Fix TFUninitLib (#6504) Supporting the Language bar... JIRA issue: CORE-19363 - Delete TFInitLib and TFUninitLib calls from ctfmon.exe. - Delete TFUninitLib from Cicero library. - Implement InitDisplayAttrbuteLib in msctfime.ime. - Improve CIC_LIBTHREAD structure. --- base/applications/ctfmon/ctfmon.cpp | 6 --- dll/ime/msctfime/msctfime.cpp | 76 +++++++++++++++++++++++++++-- dll/win32/msctf/utils.cpp | 5 ++ dll/win32/msutb/msutb.cpp | 5 ++ sdk/lib/cicero/cicbase.cpp | 10 ---- sdk/lib/cicero/cicutb.h | 10 ++-- 6 files changed, 87 insertions(+), 25 deletions(-) diff --git a/base/applications/ctfmon/ctfmon.cpp b/base/applications/ctfmon/ctfmon.cpp index 6c255f18b2e..331fd19cc37 100644 --- a/base/applications/ctfmon/ctfmon.cpp +++ b/base/applications/ctfmon/ctfmon.cpp @@ -194,9 +194,6 @@ InitApp( g_bOnWow64 = cicIsWow64(); // Is the current process on WoW64? cicGetOSInfo(&g_uACP, &g_dwOsInfo); // Get OS info - // Initialize Cicero - TFInitLib(); - // Create a mutex for Cicero g_hCicMutex = TF_CreateCicLoadMutex(&g_fWinLogon); if (!g_hCicMutex) @@ -251,9 +248,6 @@ UninitApp(VOID) // Close Tipbar Popup ClosePopupTipbar(); - // Release Cicero - TFUninitLib(); - // Close the mutex ::CloseHandle(g_hCicMutex); g_hCicMutex = NULL; diff --git a/dll/ime/msctfime/msctfime.cpp b/dll/ime/msctfime/msctfime.cpp index c1353076be1..ccd442083ab 100644 --- a/dll/ime/msctfime/msctfime.cpp +++ b/dll/ime/msctfime/msctfime.cpp @@ -10,12 +10,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(msctfime); +typedef CicArray CDispAttrPropCache; + HINSTANCE g_hInst = NULL; /* The instance of this module */ BOOL g_bWinLogon = FALSE; UINT g_uACP = CP_ACP; DWORD g_dwOSInfo = 0; BOOL gfTFInitLib = FALSE; CRITICAL_SECTION g_csLock; +CDispAttrPropCache *g_pPropCache = NULL; DEFINE_GUID(GUID_COMPARTMENT_CTFIME_DIMFLAGS, 0xA94C5FD2, 0xC471, 0x4031, 0x95, 0x46, 0x70, 0x9C, 0x17, 0x30, 0x0C, 0xB9); DEFINE_GUID(GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0x85A688F7, 0x6DC8, 0x4F17, 0xA8, 0x3A, 0xB1, 0x1C, 0x09, 0xCD, 0xD7, 0xBF); @@ -124,6 +127,33 @@ IsInteractiveUserLogon(VOID) return bOK && IsMember; } +/// @implemented +ITfCategoryMgr *GetUIMCat(PCIC_LIBTHREAD pLibThread) +{ + if (!pLibThread) + return NULL; + + if (pLibThread->m_pCategoryMgr) + return pLibThread->m_pCategoryMgr; + + if (FAILED(cicCoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, + IID_ITfCategoryMgr, (void **)&pLibThread->m_pCategoryMgr))) + { + return NULL; + } + return pLibThread->m_pCategoryMgr; +} + +/// @implemented +HRESULT LibEnumItemsInCategory(PCIC_LIBTHREAD pLibThread, REFGUID rguid, IEnumGUID **ppEnum) +{ + ITfCategoryMgr *pCat = GetUIMCat(pLibThread); + if (!pCat) + return E_FAIL; + return pCat->EnumItemsInCategory(rguid, ppEnum); +} + +/// @implemented HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread) { if (!pLibThread) @@ -135,8 +165,37 @@ HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread) pLibThread->m_pDisplayAttrMgr = NULL; } - //FIXME - return E_NOTIMPL; + if (FAILED(cicCoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL, CLSCTX_INPROC_SERVER, + IID_ITfDisplayAttributeMgr, + (void **)&pLibThread->m_pDisplayAttrMgr))) + { + return E_FAIL; + } + + IEnumGUID *pEnumGuid; + LibEnumItemsInCategory(pLibThread, GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, &pEnumGuid); + + HRESULT hr = E_OUTOFMEMORY; + + ::EnterCriticalSection(&g_csLock); + if (pEnumGuid && !g_pPropCache) + { + g_pPropCache = new(cicNoThrow) CDispAttrPropCache(); + if (g_pPropCache) + { + g_pPropCache->Add(GUID_PROP_ATTRIBUTE); + GUID guid; + while (pEnumGuid->Next(1, &guid, NULL) == S_OK) + { + if (!IsEqualGUID(guid, GUID_PROP_ATTRIBUTE)) + g_pPropCache->Add(guid); + } + hr = S_OK; + } + } + ::LeaveCriticalSection(&g_csLock); + + return hr; } HIMC GetActiveContext(VOID) @@ -3646,6 +3705,15 @@ VOID DetachIME(VOID) UnregisterImeClass(); } +EXTERN_C VOID TFUninitLib(VOID) +{ + if (g_pPropCache) + { + delete g_pPropCache; + g_pPropCache = NULL; + } +} + /// @implemented BOOL ProcessAttach(HINSTANCE hinstDLL) { @@ -3667,11 +3735,9 @@ BOOL ProcessAttach(HINSTANCE hinstDLL) return AttachIME(); } -/// @unimplemented +/// @implemented VOID ProcessDetach(HINSTANCE hinstDLL) { - // FIXME - TF_DllDetachInOther(); if (gfTFInitLib) diff --git a/dll/win32/msctf/utils.cpp b/dll/win32/msctf/utils.cpp index 4fc57a5ac0d..ec469ceef28 100644 --- a/dll/win32/msctf/utils.cpp +++ b/dll/win32/msctf/utils.cpp @@ -519,6 +519,11 @@ VOID InitCUASFlag(VOID) } } +EXTERN_C VOID TFUninitLib(VOID) +{ + // Do nothing +} + /** * @unimplemented */ diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp index 74c537ede80..912edc45598 100644 --- a/dll/win32/msutb/msutb.cpp +++ b/dll/win32/msutb/msutb.cpp @@ -6207,6 +6207,11 @@ BEGIN_OBJECT_MAP(ObjectMap) #endif END_OBJECT_MAP() +EXTERN_C VOID TFUninitLib(VOID) +{ + // Do nothing +} + /// @implemented BOOL ProcessAttach(HINSTANCE hinstDLL) { diff --git a/sdk/lib/cicero/cicbase.cpp b/sdk/lib/cicero/cicbase.cpp index cf76100e1cd..5c93f858d54 100644 --- a/sdk/lib/cicero/cicbase.cpp +++ b/sdk/lib/cicero/cicbase.cpp @@ -254,13 +254,3 @@ TFInitLib(FN_CoCreateInstance fnCoCreateInstance) _cicGetSetUserCoCreateInstance(fnCoCreateInstance); return TRUE; } - -/** - * @unimplemented - */ -EXTERN_C -VOID -TFUninitLib(VOID) -{ - //FIXME -} diff --git a/sdk/lib/cicero/cicutb.h b/sdk/lib/cicero/cicutb.h index b831ecc82bf..18bfbc874f0 100644 --- a/sdk/lib/cicero/cicutb.h +++ b/sdk/lib/cicero/cicutb.h @@ -17,10 +17,12 @@ DEFINE_GUID(IID_ITfLangBarMgr_P, 0xD72C0FA9, 0xADD5, 0x4AF0, 0x87, DEFINE_GUID(IID_ITfLangBarEventSink_P, 0x7A460360, 0xDA21, 0x4B09, 0xA8, 0xA0, 0x8A, 0x69, 0xE7, 0x28, 0xD8, 0x93); DEFINE_GUID(CLSID_MSUTBDeskBand, 0x540D8A8B, 0x1C3F, 0x4E32, 0x81, 0x32, 0x53, 0x0F, 0x6A, 0x50, 0x20, 0x90); DEFINE_GUID(CATID_DeskBand, 0x00021492, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +DEFINE_GUID( + GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, 0xB95F181B, 0xEA4C, 0x4AF1, 0x80, 0x56, 0x7C, 0x32, 0x1A, 0xBB, 0xB0, 0x91); typedef struct CIC_LIBTHREAD { - IUnknown *m_pUnknown1; + ITfCategoryMgr *m_pCategoryMgr; ITfDisplayAttributeMgr *m_pDisplayAttrMgr; } CIC_LIBTHREAD, *PCIC_LIBTHREAD; @@ -44,10 +46,10 @@ inline void TFUninitLib_Thread(PCIC_LIBTHREAD pLibThread) if (!pLibThread) return; - if (pLibThread->m_pUnknown1) + if (pLibThread->m_pCategoryMgr) { - pLibThread->m_pUnknown1->Release(); - pLibThread->m_pUnknown1 = NULL; + pLibThread->m_pCategoryMgr->Release(); + pLibThread->m_pCategoryMgr = NULL; } if (pLibThread->m_pDisplayAttrMgr) { From e706083d5027c592c75b0cc5783aa321189ceff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 13 Feb 2024 22:51:02 +0100 Subject: [PATCH 3/6] [LIBWINE] Return empty path when given a UNIX path CORE-19444 --- sdk/lib/3rdparty/libwine/path.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/lib/3rdparty/libwine/path.c b/sdk/lib/3rdparty/libwine/path.c index d8f11bdafc5..8c620024e11 100644 --- a/sdk/lib/3rdparty/libwine/path.c +++ b/sdk/lib/3rdparty/libwine/path.c @@ -61,6 +61,8 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str ) #ifdef __REACTOS__ ERR("Got absolute UNIX path name in function wine_get_dos_file_name. This is not UNIX. Please fix the caller!\n"); ERR("File name: %s\n", str); + /* Return empty path */ + return RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, 1 * sizeof(UNICODE_NULL)); #else len += 8; /* \??\unix prefix */ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; From 0610bcb3f9894f552c6f742f71d1e76a84b57dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 18 Feb 2024 23:56:09 +0100 Subject: [PATCH 4/6] [DBGHELP] Avoid call of wine_get_dos_file_name CORE-19444 --- dll/win32/dbghelp/path.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dll/win32/dbghelp/path.c b/dll/win32/dbghelp/path.c index 6639375d444..92db186be41 100644 --- a/dll/win32/dbghelp/path.c +++ b/dll/win32/dbghelp/path.c @@ -673,6 +673,7 @@ WCHAR *get_dos_file_name(const WCHAR *filename) WCHAR *dos_path; size_t len; +#ifndef __REACTOS__ if (*filename == '/') { char *unix_path; @@ -683,6 +684,7 @@ WCHAR *get_dos_file_name(const WCHAR *filename) heap_free(unix_path); } else +#endif { len = lstrlenW(filename); dos_path = heap_alloc((len + 1) * sizeof(WCHAR)); From b2ec78673d2f2fd8f41565fef070f40297e911da Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Tue, 20 Feb 2024 21:11:08 +0900 Subject: [PATCH 5/6] [MSCTFIME] Restructuring (#6505) Improve code flexibility. 3700+ lines of msctfime.cpp was too long. JIRA issue: CORE-19360 - Split msctfime.cpp code to some source files and header files. --- dll/ime/msctfime/CMakeLists.txt | 10 +- dll/ime/msctfime/bridge.cpp | 608 ++++++ dll/ime/msctfime/bridge.h | 80 + dll/ime/msctfime/compartment.cpp | 163 ++ dll/ime/msctfime/compartment.h | 44 + dll/ime/msctfime/functions.cpp | 175 ++ dll/ime/msctfime/functions.h | 63 + dll/ime/msctfime/inputcontext.cpp | 323 ++++ dll/ime/msctfime/inputcontext.h | 91 + dll/ime/msctfime/msctfime.cpp | 3003 +---------------------------- dll/ime/msctfime/msctfime.h | 17 + dll/ime/msctfime/profile.cpp | 173 ++ dll/ime/msctfime/profile.h | 51 + dll/ime/msctfime/sinks.cpp | 539 ++++++ dll/ime/msctfime/sinks.h | 166 ++ dll/ime/msctfime/tls.cpp | 56 + dll/ime/msctfime/tls.h | 74 + dll/ime/msctfime/ui.cpp | 393 ++++ dll/ime/msctfime/ui.h | 68 + 19 files changed, 3177 insertions(+), 2920 deletions(-) create mode 100644 dll/ime/msctfime/bridge.cpp create mode 100644 dll/ime/msctfime/bridge.h create mode 100644 dll/ime/msctfime/compartment.cpp create mode 100644 dll/ime/msctfime/compartment.h create mode 100644 dll/ime/msctfime/functions.cpp create mode 100644 dll/ime/msctfime/functions.h create mode 100644 dll/ime/msctfime/inputcontext.cpp create mode 100644 dll/ime/msctfime/inputcontext.h create mode 100644 dll/ime/msctfime/profile.cpp create mode 100644 dll/ime/msctfime/profile.h create mode 100644 dll/ime/msctfime/sinks.cpp create mode 100644 dll/ime/msctfime/sinks.h create mode 100644 dll/ime/msctfime/tls.cpp create mode 100644 dll/ime/msctfime/tls.h create mode 100644 dll/ime/msctfime/ui.cpp create mode 100644 dll/ime/msctfime/ui.h diff --git a/dll/ime/msctfime/CMakeLists.txt b/dll/ime/msctfime/CMakeLists.txt index 5a034398964..288c14afc7f 100644 --- a/dll/ime/msctfime/CMakeLists.txt +++ b/dll/ime/msctfime/CMakeLists.txt @@ -5,7 +5,15 @@ include_directories( spec2def(msctfime.ime msctfime.spec) list(APPEND SOURCE - msctfime.cpp) + bridge.cpp + compartment.cpp + functions.cpp + inputcontext.cpp + msctfime.cpp + profile.cpp + sinks.cpp + tls.cpp + ui.cpp) file(GLOB msctfime_rc_deps res/*.*) add_rc_deps(msctfime.rc ${msctfime_rc_deps}) diff --git a/dll/ime/msctfime/bridge.cpp b/dll/ime/msctfime/bridge.cpp new file mode 100644 index 00000000000..de9e6ba10ef --- /dev/null +++ b/dll/ime/msctfime/bridge.cpp @@ -0,0 +1,608 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Bridge + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @implemented +CicBridge::CicBridge() +{ + m_bImmxInited = FALSE; + m_bUnknown1 = FALSE; + m_bDeactivating = FALSE; + m_bUnknown2 = FALSE; + m_pKeystrokeMgr = NULL; + m_pDocMgr = NULL; + m_pThreadMgrEventSink = NULL; + m_cliendId = 0; + m_cRefs = 1; +} + +/// @implemented +STDMETHODIMP CicBridge::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + *ppvObj = NULL; + + if (!IsEqualIID(riid, IID_ITfSysHookSink)) + return E_NOINTERFACE; + + *ppvObj = this; + AddRef(); + + return S_OK; +} + +/// @implemented +STDMETHODIMP_(ULONG) CicBridge::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CicBridge::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +CicBridge::~CicBridge() +{ + TLS *pTLS = TLS::PeekTLS(); + if (!pTLS || !pTLS->m_pThreadMgr) + return; + + if (SUCCEEDED(DeactivateIMMX(pTLS, pTLS->m_pThreadMgr))) + UnInitIMMX(pTLS); +} + +void CicBridge::GetDocumentManager(_Inout_ CicIMCCLock& imeContext) +{ + CicInputContext *pCicIC = imeContext.get().m_pCicIC; + if (pCicIC) + { + m_pDocMgr = pCicIC->m_pDocumentMgr; + m_pDocMgr->AddRef(); + } + else + { + m_pDocMgr->Release(); + m_pDocMgr = NULL; + } +} + +/// @unimplemented +HRESULT +CicBridge::CreateInputContext( + _Inout_ TLS *pTLS, + _In_ HIMC hIMC) +{ + CicIMCLock imcLock(hIMC); + HRESULT hr = imcLock.m_hr; + if (!imcLock) + hr = E_FAIL; + if (FAILED(hr)) + return hr; + + if (!imcLock.get().hCtfImeContext) + { + HIMCC hCtfImeContext = ImmCreateIMCC(sizeof(CTFIMECONTEXT)); + if (!hCtfImeContext) + return E_OUTOFMEMORY; + imcLock.get().hCtfImeContext = hCtfImeContext; + } + + CicIMCCLock imeContext(imcLock.get().hCtfImeContext); + CicInputContext *pCicIC = imeContext.get().m_pCicIC; + if (!pCicIC) + { + pCicIC = new(cicNoThrow) CicInputContext(m_cliendId, &m_LibThread, hIMC); + if (!pCicIC) + { + imeContext.unlock(); + imcLock.unlock(); + DestroyInputContext(pTLS, hIMC); + return E_OUTOFMEMORY; + } + + if (!pTLS->m_pThreadMgr) + { + pCicIC->Release(); + imeContext.unlock(); + imcLock.unlock(); + DestroyInputContext(pTLS, hIMC); + return E_NOINTERFACE; + } + + imeContext.get().m_pCicIC = pCicIC; + } + + hr = pCicIC->CreateInputContext(pTLS->m_pThreadMgr, imcLock); + if (FAILED(hr)) + { + pCicIC->Release(); + imeContext.get().m_pCicIC = NULL; + } + else + { + if (imcLock.get().hWnd && imcLock.get().hWnd == ::GetFocus()) + { + GetDocumentManager(imeContext); + //FIXME + } + } + + return E_NOTIMPL; +} + +/// @implemented +HRESULT CicBridge::DestroyInputContext(TLS *pTLS, HIMC hIMC) +{ + CicIMCLock imcLock(hIMC); + HRESULT hr = imcLock.m_hr; + if (!imcLock) + hr = E_FAIL; + if (FAILED(hr)) + return hr; + + hr = E_FAIL; + CicIMCCLock imeContext(imcLock.get().hCtfImeContext); + if (imeContext) + hr = imeContext.m_hr; + + if (SUCCEEDED(hr) && !(imeContext.get().m_dwCicFlags & 1)) + { + imeContext.get().m_dwCicFlags |= 1; + + CicInputContext *pCicIC = imeContext.get().m_pCicIC; + if (pCicIC) + { + imeContext.get().m_pCicIC = NULL; + hr = pCicIC->DestroyInputContext(); + pCicIC->Release(); + imeContext.get().m_pCicIC = NULL; + } + } + + if (imcLock.get().hCtfImeContext) + { + ImmDestroyIMCC(imcLock.get().hCtfImeContext); + imcLock.get().hCtfImeContext = NULL; + hr = S_OK; + } + + return hr; +} + +ITfContext * +CicBridge::GetInputContext(CicIMCCLock& imeContext) +{ + CicInputContext *pCicIC = imeContext.get().m_pCicIC; + if (!pCicIC) + return NULL; + return pCicIC->m_pContext; +} + +/// @unimplemented +HRESULT CicBridge::OnSetOpenStatus( + TLS *pTLS, + ITfThreadMgr_P *pThreadMgr, + CicIMCLock& imcLock, + CicInputContext *pCicIC) +{ + return E_NOTIMPL; +} + +/// Selects the IME context. +/// @implemented +HRESULT +CicBridge::SelectEx( + _Inout_ TLS *pTLS, + _Inout_ ITfThreadMgr_P *pThreadMgr, + _In_ HIMC hIMC, + _In_ BOOL fSelect, + _In_ HKL hKL) +{ + CicIMCLock imcLock(hIMC); + if (FAILED(imcLock.m_hr)) + return imcLock.m_hr; + + CicIMCCLock imeContext(imcLock.get().hCtfImeContext); + if (!imeContext) + imeContext.m_hr = E_FAIL; + if (FAILED(imeContext.m_hr)) + return imeContext.m_hr; + + CicInputContext *pCicIC = imeContext.get().m_pCicIC; + if (pCicIC) + pCicIC->m_bSelecting = TRUE; + + if (fSelect) + { + if (pCicIC) + pCicIC->m_dwUnknown6[1] &= ~1; + if (imcLock.get().fOpen) + OnSetOpenStatus(pTLS, pThreadMgr, imcLock, pCicIC); + } + else + { + ITfContext *pContext = GetInputContext(imeContext); + pThreadMgr->RequestPostponedLock(pContext); + if (pCicIC) + pCicIC->m_bSelecting = FALSE; + if (pContext) + pContext->Release(); + } + + return imeContext.m_hr; +} + +/// Used in CicBridge::EnumCreateInputContextCallback and +/// CicBridge::EnumDestroyInputContextCallback. +typedef struct ENUM_CREATE_DESTROY_IC +{ + TLS *m_pTLS; + CicBridge *m_pBridge; +} ENUM_CREATE_DESTROY_IC, *PENUM_CREATE_DESTROY_IC; + +/// Creates input context for the current thread. +/// @implemented +BOOL CALLBACK CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam) +{ + PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; + pData->m_pBridge->CreateInputContext(pData->m_pTLS, hIMC); + return TRUE; +} + +/// Destroys input context for the current thread. +/// @implemented +BOOL CALLBACK CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam) +{ + PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; + pData->m_pBridge->DestroyInputContext(pData->m_pTLS, hIMC); + return TRUE; +} + +/// @implemented +HRESULT +CicBridge::ActivateIMMX( + _Inout_ TLS *pTLS, + _Inout_ ITfThreadMgr_P *pThreadMgr) +{ + HRESULT hr = pThreadMgr->ActivateEx(&m_cliendId, 1); + if (hr != S_OK) + { + m_cliendId = 0; + return E_FAIL; + } + + if (m_cActivateLocks++ != 0) + return S_OK; + + ITfSourceSingle *pSource = NULL; + hr = pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void**)&pSource); + if (FAILED(hr)) + { + DeactivateIMMX(pTLS, pThreadMgr); + return hr; + } + + CFunctionProvider *pProvider = new(cicNoThrow) CFunctionProvider(m_cliendId); + if (!pProvider) + { + hr = E_FAIL; + goto Finish; + } + + pSource->AdviseSingleSink(m_cliendId, IID_ITfFunctionProvider, pProvider); + pProvider->Release(); + + if (!m_pDocMgr) + { + hr = pThreadMgr->CreateDocumentMgr(&m_pDocMgr); + if (FAILED(hr)) + { + hr = E_FAIL; + goto Finish; + } + + SetCompartmentDWORD(m_cliendId, m_pDocMgr, GUID_COMPARTMENT_CTFIME_DIMFLAGS, TRUE, FALSE); + } + + pThreadMgr->SetSysHookSink(this); + + hr = S_OK; + if (pTLS->m_bDestroyed) + { + ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; + ImmEnumInputContext(0, CicBridge::EnumCreateInputContextCallback, (LPARAM)&Data); + } + +Finish: + if (FAILED(hr)) + DeactivateIMMX(pTLS, pThreadMgr); + if (pSource) + pSource->Release(); + return hr; +} + +/// @implemented +HRESULT +CicBridge::DeactivateIMMX( + _Inout_ TLS *pTLS, + _Inout_ ITfThreadMgr_P *pThreadMgr) +{ + if (m_bDeactivating) + return TRUE; + + m_bDeactivating = TRUE; + + if (m_cliendId) + { + ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; + ImmEnumInputContext(0, CicBridge::EnumDestroyInputContextCallback, (LPARAM)&Data); + pTLS->m_bDestroyed = TRUE; + + ITfSourceSingle *pSource = NULL; + if (pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) + pSource->UnadviseSingleSink(m_cliendId, IID_ITfFunctionProvider); + + m_cliendId = 0; + + while (m_cActivateLocks > 0) + { + --m_cActivateLocks; + pThreadMgr->Deactivate(); + } + + if (pSource) + pSource->Release(); + } + + if (m_pDocMgr) + { + m_pDocMgr->Release(); + m_pDocMgr = NULL; + } + + pThreadMgr->SetSysHookSink(NULL); + + m_bDeactivating = FALSE; + + return S_OK; +} + +/// @implemented +HRESULT +CicBridge::InitIMMX(_Inout_ TLS *pTLS) +{ + if (m_bImmxInited) + return S_OK; + + HRESULT hr = S_OK; + if (!pTLS->m_pThreadMgr) + { + ITfThreadMgr *pThreadMgr = NULL; + hr = TF_CreateThreadMgr(&pThreadMgr); + if (FAILED(hr)) + return E_FAIL; + + hr = pThreadMgr->QueryInterface(IID_ITfThreadMgr_P, (void **)&pTLS->m_pThreadMgr); + if (pThreadMgr) + pThreadMgr->Release(); + if (FAILED(hr)) + return E_FAIL; + } + + if (!m_pThreadMgrEventSink) + { + m_pThreadMgrEventSink = + new(cicNoThrow) CThreadMgrEventSink(CThreadMgrEventSink::DIMCallback, NULL, NULL); + if (!m_pThreadMgrEventSink) + { + UnInitIMMX(pTLS); + return E_FAIL; + } + } + + m_pThreadMgrEventSink->SetCallbackPV(m_pThreadMgrEventSink); + m_pThreadMgrEventSink->_Advise(pTLS->m_pThreadMgr); + + if (!pTLS->m_pProfile) + { + pTLS->m_pProfile = new(cicNoThrow) CicProfile(); + if (!pTLS->m_pProfile) + return E_OUTOFMEMORY; + + hr = pTLS->m_pProfile->InitProfileInstance(pTLS); + if (FAILED(hr)) + { + UnInitIMMX(pTLS); + return E_FAIL; + } + } + + hr = pTLS->m_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr_P, (void **)&m_pKeystrokeMgr); + if (FAILED(hr)) + { + UnInitIMMX(pTLS); + return E_FAIL; + } + + hr = InitDisplayAttrbuteLib(&m_LibThread); + if (FAILED(hr)) + { + UnInitIMMX(pTLS); + return E_FAIL; + } + + m_bImmxInited = TRUE; + return S_OK; +} + +/// @implemented +BOOL CicBridge::UnInitIMMX(_Inout_ TLS *pTLS) +{ + UninitDisplayAttrbuteLib(&m_LibThread); + TFUninitLib_Thread(&m_LibThread); + + if (m_pKeystrokeMgr) + { + m_pKeystrokeMgr->Release(); + m_pKeystrokeMgr = NULL; + } + + if (pTLS->m_pProfile) + { + pTLS->m_pProfile->Release(); + pTLS->m_pProfile = NULL; + } + + if (m_pThreadMgrEventSink) + { + m_pThreadMgrEventSink->_Unadvise(); + m_pThreadMgrEventSink->Release(); + m_pThreadMgrEventSink = NULL; + } + + if (pTLS->m_pThreadMgr) + { + pTLS->m_pThreadMgr->Release(); + pTLS->m_pThreadMgr = NULL; + } + + m_bImmxInited = FALSE; + return TRUE; +} + +/// @implemented +STDMETHODIMP CicBridge::OnPreFocusDIM(HWND hwnd) +{ + return S_OK; +} + +/// @unimplemented +STDMETHODIMP CicBridge::OnSysKeyboardProc(UINT, LONG) +{ + return E_NOTIMPL; +} + +/// @implemented +STDMETHODIMP CicBridge::OnSysShellProc(INT, UINT, LONG) +{ + return S_OK; +} + +/// @implemented +void +CicBridge::PostTransMsg( + _In_ HWND hWnd, + _In_ INT cTransMsgs, + _In_ const TRANSMSG *pTransMsgs) +{ + for (INT i = 0; i < cTransMsgs; ++i, ++pTransMsgs) + { + ::PostMessageW(hWnd, pTransMsgs->message, pTransMsgs->wParam, pTransMsgs->lParam); + } +} + +/// @implemented +HRESULT +CicBridge::ConfigureGeneral( + _Inout_ TLS* pTLS, + _In_ ITfThreadMgr *pThreadMgr, + _In_ HKL hKL, + _In_ HWND hWnd) +{ + CicProfile *pProfile = pTLS->m_pProfile; + if (!pProfile) + return E_OUTOFMEMORY; + + TF_LANGUAGEPROFILE profile; + HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); + if (FAILED(hr)) + return hr; + + ITfFunctionProvider *pProvider = NULL; + hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); + if (FAILED(hr)) + return hr; + + ITfFnConfigure *pFnConfigure = NULL; + hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigure, (IUnknown**)&pFnConfigure); + if (FAILED(hr)) + { + pProvider->Release(); + return hr; + } + + hr = pFnConfigure->Show(hWnd, profile.langid, profile.guidProfile); + + pFnConfigure->Release(); + pProvider->Release(); + return hr; +} + +/// @implemented +HRESULT +CicBridge::ConfigureRegisterWord( + _Inout_ TLS* pTLS, + _In_ ITfThreadMgr *pThreadMgr, + _In_ HKL hKL, + _In_ HWND hWnd, + _Inout_opt_ LPVOID lpData) +{ + CicProfile *pProfile = pTLS->m_pProfile; + if (!pProfile) + return E_OUTOFMEMORY; + + TF_LANGUAGEPROFILE profile; + HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); + if (FAILED(hr)) + return hr; + + ITfFunctionProvider *pProvider = NULL; + hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); + if (FAILED(hr)) + return hr; + + ITfFnConfigureRegisterWord *pFunction = NULL; + hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigureRegisterWord, (IUnknown**)&pFunction); + if (FAILED(hr)) + { + pProvider->Release(); + return hr; + } + + REGISTERWORDW* pRegWord = (REGISTERWORDW*)lpData; + if (pRegWord) + { + if (pRegWord->lpWord) + { + hr = E_OUTOFMEMORY; + BSTR bstrWord = SysAllocString(pRegWord->lpWord); + if (bstrWord) + { + hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, bstrWord); + SysFreeString(bstrWord); + } + } + else + { + hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, NULL); + } + } + + pProvider->Release(); + pFunction->Release(); + return hr; +} diff --git a/dll/ime/msctfime/bridge.h b/dll/ime/msctfime/bridge.h new file mode 100644 index 00000000000..c8b8441203d --- /dev/null +++ b/dll/ime/msctfime/bridge.h @@ -0,0 +1,80 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Bridge + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +#include "sinks.h" +#include "tls.h" + +class CicBridge : public ITfSysHookSink +{ +protected: + LONG m_cRefs; + BOOL m_bImmxInited; + BOOL m_bUnknown1; + BOOL m_bDeactivating; + DWORD m_cActivateLocks; + ITfKeystrokeMgr *m_pKeystrokeMgr; + ITfDocumentMgr *m_pDocMgr; + CThreadMgrEventSink *m_pThreadMgrEventSink; + TfClientId m_cliendId; + CIC_LIBTHREAD m_LibThread; + BOOL m_bUnknown2; + + static BOOL CALLBACK EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam); + static BOOL CALLBACK EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam); + +public: + CicBridge(); + virtual ~CicBridge(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfSysHookSink interface + STDMETHODIMP OnPreFocusDIM(HWND hwnd) override; + STDMETHODIMP OnSysKeyboardProc(UINT, LONG) override; + STDMETHODIMP OnSysShellProc(INT, UINT, LONG) override; + + HRESULT InitIMMX(_Inout_ TLS *pTLS); + BOOL UnInitIMMX(_Inout_ TLS *pTLS); + HRESULT ActivateIMMX(_Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr); + HRESULT DeactivateIMMX(_Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr); + + HRESULT CreateInputContext(TLS *pTLS, HIMC hIMC); + HRESULT DestroyInputContext(TLS *pTLS, HIMC hIMC); + ITfContext *GetInputContext(CicIMCCLock& imeContext); + + HRESULT SelectEx( + _Inout_ TLS *pTLS, + _Inout_ ITfThreadMgr_P *pThreadMgr, + _In_ HIMC hIMC, + _In_ BOOL fSelect, + _In_ HKL hKL); + HRESULT OnSetOpenStatus( + TLS *pTLS, + ITfThreadMgr_P *pThreadMgr, + CicIMCLock& imcLock, + CicInputContext *pCicIC); + + void PostTransMsg(_In_ HWND hWnd, _In_ INT cTransMsgs, _In_ const TRANSMSG *pTransMsgs); + void GetDocumentManager(_Inout_ CicIMCCLock& imeContext); + + HRESULT + ConfigureGeneral(_Inout_ TLS* pTLS, + _In_ ITfThreadMgr *pThreadMgr, + _In_ HKL hKL, + _In_ HWND hWnd); + HRESULT ConfigureRegisterWord( + _Inout_ TLS* pTLS, + _In_ ITfThreadMgr *pThreadMgr, + _In_ HKL hKL, + _In_ HWND hWnd, + _Inout_opt_ LPVOID lpData); +}; diff --git a/dll/ime/msctfime/compartment.cpp b/dll/ime/msctfime/compartment.cpp new file mode 100644 index 00000000000..d92b1b526f4 --- /dev/null +++ b/dll/ime/msctfime/compartment.cpp @@ -0,0 +1,163 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Supporting compartments + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @implemented +HRESULT +GetCompartment( + IUnknown *pUnknown, + REFGUID rguid, + ITfCompartment **ppComp, + BOOL bThread) +{ + *ppComp = NULL; + + ITfThreadMgr *pThreadMgr = NULL; + ITfCompartmentMgr *pCompMgr = NULL; + + HRESULT hr; + if (bThread) + { + hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); + if (FAILED(hr)) + return hr; + + hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); + } + else + { + hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); + } + + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + if (pCompMgr) + { + hr = pCompMgr->GetCompartment(rguid, ppComp); + pCompMgr->Release(); + } + } + + if (pThreadMgr) + pThreadMgr->Release(); + + return hr; +} + +/// @implemented +HRESULT +SetCompartmentDWORD( + TfEditCookie cookie, + IUnknown *pUnknown, + REFGUID rguid, + DWORD dwValue, + BOOL bThread) +{ + ITfCompartment *pComp = NULL; + HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); + if (FAILED(hr)) + return hr; + + VARIANT vari; + V_I4(&vari) = dwValue; + V_VT(&vari) = VT_I4; + hr = pComp->SetValue(cookie, &vari); + + pComp->Release(); + return hr; +} + +/// @implemented +HRESULT +GetCompartmentDWORD( + IUnknown *pUnknown, + REFGUID rguid, + LPDWORD pdwValue, + BOOL bThread) +{ + *pdwValue = 0; + + ITfCompartment *pComp = NULL; + HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); + if (FAILED(hr)) + return hr; + + VARIANT vari; + hr = pComp->GetValue(&vari); + if (hr == S_OK) + *pdwValue = V_I4(&vari); + + pComp->Release(); + return hr; +} + +/// @implemented +HRESULT +SetCompartmentUnknown( + TfEditCookie cookie, + IUnknown *pUnknown, + REFGUID rguid, + IUnknown *punkValue) +{ + ITfCompartment *pComp = NULL; + HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, FALSE); + if (FAILED(hr)) + return hr; + + VARIANT vari; + V_UNKNOWN(&vari) = punkValue; + V_VT(&vari) = VT_UNKNOWN; + hr = pComp->SetValue(cookie, &vari); + + pComp->Release(); + return hr; +} + +/// @implemented +HRESULT +ClearCompartment( + TfClientId tid, + IUnknown *pUnknown, + REFGUID rguid, + BOOL bThread) +{ + ITfCompartmentMgr *pCompMgr = NULL; + ITfThreadMgr *pThreadMgr = NULL; + + HRESULT hr; + if (bThread) + { + hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); + if (FAILED(hr)) + return hr; + + hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); + } + else + { + hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); + } + + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + if (pCompMgr) + { + hr = pCompMgr->ClearCompartment(tid, rguid); + pCompMgr->Release(); + } + } + + if (pThreadMgr) + pThreadMgr->Release(); + + return hr; +} diff --git a/dll/ime/msctfime/compartment.h b/dll/ime/msctfime/compartment.h new file mode 100644 index 00000000000..88805566832 --- /dev/null +++ b/dll/ime/msctfime/compartment.h @@ -0,0 +1,44 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Supporting compartments + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +HRESULT +GetCompartment( + IUnknown *pUnknown, + REFGUID rguid, + ITfCompartment **ppComp, + BOOL bThread); + +HRESULT +SetCompartmentDWORD( + TfEditCookie cookie, + IUnknown *pUnknown, + REFGUID rguid, + DWORD dwValue, + BOOL bThread); + +HRESULT +GetCompartmentDWORD( + IUnknown *pUnknown, + REFGUID rguid, + LPDWORD pdwValue, + BOOL bThread); + +HRESULT +SetCompartmentUnknown( + TfEditCookie cookie, + IUnknown *pUnknown, + REFGUID rguid, + IUnknown *punkValue); + +HRESULT +ClearCompartment( + TfClientId tid, + IUnknown *pUnknown, + REFGUID rguid, + BOOL bThread); diff --git a/dll/ime/msctfime/functions.cpp b/dll/ime/msctfime/functions.cpp new file mode 100644 index 00000000000..c9832f90cff --- /dev/null +++ b/dll/ime/msctfime/functions.cpp @@ -0,0 +1,175 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: The functions of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @implemented +CFunctionProviderBase::CFunctionProviderBase(_In_ TfClientId clientId) +{ + m_clientId = clientId; + m_guid = GUID_NULL; + m_bstr = NULL; + m_cRefs = 1; +} + +/// @implemented +CFunctionProviderBase::~CFunctionProviderBase() +{ + if (!DllShutdownInProgress()) + ::SysFreeString(m_bstr); +} + +/// @implemented +BOOL +CFunctionProviderBase::Init( + _In_ REFGUID rguid, + _In_ LPCWSTR psz) +{ + m_bstr = ::SysAllocString(psz); + m_guid = rguid; + return (m_bstr != NULL); +} + +/// @implemented +STDMETHODIMP +CFunctionProviderBase::QueryInterface( + _In_ REFIID riid, + _Out_ LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfFunctionProvider)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CFunctionProviderBase::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CFunctionProviderBase::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +STDMETHODIMP CFunctionProviderBase::GetType(_Out_ GUID *guid) +{ + *guid = m_guid; + return S_OK; +} + +/// @implemented +STDMETHODIMP CFunctionProviderBase::GetDescription(_Out_ BSTR *desc) +{ + *desc = ::SysAllocString(m_bstr); + return (*desc ? S_OK : E_OUTOFMEMORY); +} + +/***********************************************************************/ + +/// @implemented +CFunctionProvider::CFunctionProvider(_In_ TfClientId clientId) : CFunctionProviderBase(clientId) +{ + Init(CLSID_CAImmLayer, L"MSCTFIME::Function Provider"); +} + +/// @implemented +STDMETHODIMP +CFunctionProvider::GetFunction( + _In_ REFGUID guid, + _In_ REFIID riid, + _Out_ IUnknown **func) +{ + *func = NULL; + + if (IsEqualGUID(guid, GUID_NULL) && + IsEqualIID(riid, IID_IAImmFnDocFeed)) + { + *func = new(cicNoThrow) CFnDocFeed(); + if (*func) + return S_OK; + } + + return E_NOINTERFACE; +} + +/***********************************************************************/ + +CFnDocFeed::CFnDocFeed() +{ + m_cRefs = 1; +} + +CFnDocFeed::~CFnDocFeed() +{ +} + +/// @implemented +STDMETHODIMP CFnDocFeed::QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IAImmFnDocFeed)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CFnDocFeed::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CFnDocFeed::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @unimplemented +STDMETHODIMP CFnDocFeed::DocFeed() +{ + return E_NOTIMPL; +} + +/// @unimplemented +STDMETHODIMP CFnDocFeed::ClearDocFeedBuffer() +{ + return E_NOTIMPL; +} + +/// @unimplemented +STDMETHODIMP CFnDocFeed::StartReconvert() +{ + return E_NOTIMPL; +} + +/// @unimplemented +STDMETHODIMP CFnDocFeed::StartUndoCompositionString() +{ + return E_NOTIMPL; +} diff --git a/dll/ime/msctfime/functions.h b/dll/ime/msctfime/functions.h new file mode 100644 index 00000000000..6938162a6e5 --- /dev/null +++ b/dll/ime/msctfime/functions.h @@ -0,0 +1,63 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: The functions of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +class CFunctionProviderBase : public ITfFunctionProvider +{ +protected: + TfClientId m_clientId; + GUID m_guid; + BSTR m_bstr; + LONG m_cRefs; + +public: + CFunctionProviderBase(_In_ TfClientId clientId); + virtual ~CFunctionProviderBase(); + + // IUnknown interface + STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfFunctionProvider interface + STDMETHODIMP GetType(_Out_ GUID *guid) override; + STDMETHODIMP GetDescription(_Out_ BSTR *desc) override; + //STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) = 0; + + BOOL Init(_In_ REFGUID rguid, _In_ LPCWSTR psz); +}; + +/***********************************************************************/ + +class CFunctionProvider : public CFunctionProviderBase +{ +public: + CFunctionProvider(_In_ TfClientId clientId); + + STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) override; +}; + +/***********************************************************************/ + +class CFnDocFeed : public IAImmFnDocFeed +{ + LONG m_cRefs; + +public: + CFnDocFeed(); + virtual ~CFnDocFeed(); + + // IUnknown interface + STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // IAImmFnDocFeed interface + STDMETHODIMP DocFeed() override; + STDMETHODIMP ClearDocFeedBuffer() override; + STDMETHODIMP StartReconvert() override; + STDMETHODIMP StartUndoCompositionString() override; +}; diff --git a/dll/ime/msctfime/inputcontext.cpp b/dll/ime/msctfime/inputcontext.cpp new file mode 100644 index 00000000000..1bdf64cb62e --- /dev/null +++ b/dll/ime/msctfime/inputcontext.cpp @@ -0,0 +1,323 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Input Context of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @unimplemented +CicInputContext::CicInputContext( + _In_ TfClientId cliendId, + _Inout_ PCIC_LIBTHREAD pLibThread, + _In_ HIMC hIMC) +{ + m_hIMC = hIMC; + m_guid = GUID_NULL; + m_dwQueryPos = 0; + m_cRefs = 1; +} + +/// @implemented +STDMETHODIMP CicInputContext::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + *ppvObj = NULL; + + if (IsEqualIID(riid, IID_ITfContextOwnerCompositionSink)) + { + *ppvObj = static_cast(this); + AddRef(); + return S_OK; + } + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCleanupContextSink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CicInputContext::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CicInputContext::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +STDMETHODIMP +CicInputContext::OnStartComposition( + ITfCompositionView *pComposition, + BOOL *pfOk) +{ + if ((m_cCompLocks <= 0) || m_dwUnknown6_5) + { + *pfOk = TRUE; + ++m_cCompLocks; + } + else + { + *pfOk = FALSE; + } + return S_OK; +} + +/// @implemented +STDMETHODIMP +CicInputContext::OnUpdateComposition( + ITfCompositionView *pComposition, + ITfRange *pRangeNew) +{ + return S_OK; +} + +/// @implemented +STDMETHODIMP +CicInputContext::OnEndComposition( + ITfCompositionView *pComposition) +{ + --m_cCompLocks; + return S_OK; +} + +/// @implemented +HRESULT +CicInputContext::GetGuidAtom( + _Inout_ CicIMCLock& imcLock, + _In_ BYTE iAtom, + _Out_opt_ LPDWORD pdwGuidAtom) +{ + CicIMCCLock imeContext(imcLock.get().hCompStr); + HRESULT hr = imeContext.m_hr; + if (!imeContext) + hr = E_FAIL; + if (FAILED(hr)) + return hr; + + hr = E_FAIL; + if (iAtom < m_cGuidAtoms) + { + *pdwGuidAtom = m_adwGuidAtoms[iAtom]; + hr = S_OK; + } + + return hr; +} + +/// @unimplemented +HRESULT +CicInputContext::CreateInputContext( + _Inout_ ITfThreadMgr *pThreadMgr, + _Inout_ CicIMCLock& imcLock) +{ + //FIXME + return E_NOTIMPL; +} + +/// @unimplemented +HRESULT +CicInputContext::DestroyInputContext() +{ + ITfSourceSingle *pSource = NULL; + + if (m_pContext && m_pContext->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) + pSource->UnadviseSingleSink(m_clientId, IID_ITfCleanupContextSink); + + //FIXME: m_dwUnknown5 + + if (m_pTextEventSink) + { + m_pTextEventSink->_Unadvise(); + m_pTextEventSink->Release(); + m_pTextEventSink = NULL; + } + + if (m_pCompEventSink2) + { + m_pCompEventSink2->_Unadvise(); + m_pCompEventSink2->Release(); + m_pCompEventSink2 = NULL; + } + + if (m_pCompEventSink1) + { + m_pCompEventSink1->_Unadvise(); + m_pCompEventSink1->Release(); + m_pCompEventSink1 = NULL; + } + + //FIXME: m_pInputContextOwner + + if (m_pDocumentMgr) + m_pDocumentMgr->Pop(1); + + if (m_pContext) + { + ClearCompartment(m_clientId, m_pContext, GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0); + m_pContext->Release(); + m_pContext = NULL; + } + + if (m_pContextOwnerServices) + { + m_pContextOwnerServices->Release(); + m_pContextOwnerServices = NULL; + } + + // FIXME: m_pICOwnerCallback + + if (m_pDocumentMgr) + { + m_pDocumentMgr->Release(); + m_pDocumentMgr = NULL; + } + + if (pSource) + pSource->Release(); + + return S_OK; +} + +/// @implemented +STDMETHODIMP +CicInputContext::OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) +{ + return S_OK; +} + +/// @implemented +STDMETHODIMP +CicInputContext::OnCleanupContext( + _In_ TfEditCookie ecWrite, + _Inout_ ITfContext *pic) +{ + TLS *pTLS = TLS::PeekTLS(); + if (!pTLS || !pTLS->m_pProfile) + return E_OUTOFMEMORY; + + LANGID LangID; + pTLS->m_pProfile->GetLangId(&LangID); + + IMEINFO IMEInfo; + WCHAR szPath[MAX_PATH]; + if (Inquire(&IMEInfo, szPath, 0, (HKL)UlongToHandle(LangID)) != S_OK) + return E_FAIL; + + ITfProperty *pProp = NULL; + if (!(IMEInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)) + return S_OK; + + HRESULT hr = pic->GetProperty(GUID_PROP_COMPOSING, &pProp); + if (FAILED(hr)) + return S_OK; + + IEnumTfRanges *pRanges = NULL; + hr = pProp->EnumRanges(ecWrite, &pRanges, NULL); + if (SUCCEEDED(hr)) + { + ITfRange *pRange = NULL; + while (pRanges->Next(1, &pRange, 0) == S_OK) + { + VARIANT vari; + V_VT(&vari) = VT_EMPTY; + pProp->GetValue(ecWrite, pRange, &vari); + if (V_VT(&vari) == VT_I4) + { + if (V_I4(&vari)) + pProp->Clear(ecWrite, pRange); + } + pRange->Release(); + pRange = NULL; + } + pRanges->Release(); + } + pProp->Release(); + + return S_OK; +} + +/// Retrieves the IME information. +/// @implemented +HRESULT +Inquire( + _Out_ LPIMEINFO lpIMEInfo, + _Out_ LPWSTR lpszWndClass, + _In_ DWORD dwSystemInfoFlags, + _In_ HKL hKL) +{ + if (!lpIMEInfo) + return E_OUTOFMEMORY; + + StringCchCopyW(lpszWndClass, 64, L"MSCTFIME UI"); + lpIMEInfo->dwPrivateDataSize = 0; + + switch (LOWORD(hKL)) // Language ID + { + case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): // Japanese + { + lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | + IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | + IME_PROP_KBD_CHAR_FIRST; + lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_KATAKANA | + IME_CMODE_NATIVE; + lpIMEInfo->fdwSentenceCaps = IME_SMODE_CONVERSATION | IME_SMODE_PLAURALCLAUSE; + lpIMEInfo->fdwSelectCaps = SELECT_CAP_SENTENCE | SELECT_CAP_CONVERSION; + lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | + SCS_CAP_COMPSTR; + lpIMEInfo->fdwUICaps = UI_CAP_ROT90; + break; + } + case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): // Korean + { + lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | + IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | + IME_PROP_KBD_CHAR_FIRST; + lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; + lpIMEInfo->fdwSentenceCaps = 0; + lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_COMPSTR; + lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; + lpIMEInfo->fdwUICaps = UI_CAP_ROT90; + break; + } + case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): // Simplified Chinese + case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): // Traditional Chinese + { + lpIMEInfo->fdwProperty = IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | + IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; + lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; + lpIMEInfo->fdwSentenceCaps = SELECT_CAP_CONVERSION; + lpIMEInfo->fdwSelectCaps = 0; + lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | + SCS_CAP_COMPSTR; + lpIMEInfo->fdwUICaps = UI_CAP_ROT90; + break; + } + default: // Otherwise + { + lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; + lpIMEInfo->fdwConversionCaps = 0; + lpIMEInfo->fdwSentenceCaps = 0; + lpIMEInfo->fdwSCSCaps = 0; + lpIMEInfo->fdwUICaps = 0; + lpIMEInfo->fdwSelectCaps = 0; + break; + } + } + + return S_OK; +} diff --git a/dll/ime/msctfime/inputcontext.h b/dll/ime/msctfime/inputcontext.h new file mode 100644 index 00000000000..2273161926e --- /dev/null +++ b/dll/ime/msctfime/inputcontext.h @@ -0,0 +1,91 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Input Context of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +#include "sinks.h" + +class CInputContextOwnerCallBack; +class CInputContextOwner; + +HRESULT +Inquire( + _Out_ LPIMEINFO lpIMEInfo, + _Out_ LPWSTR lpszWndClass, + _In_ DWORD dwSystemInfoFlags, + _In_ HKL hKL); + +/*********************************************************************** + * CicInputContext + * + * The msctfime.ime's input context. + */ +class CicInputContext + : public ITfCleanupContextSink + , public ITfContextOwnerCompositionSink + , public ITfCompositionSink +{ +public: + LONG m_cRefs; + HIMC m_hIMC; + ITfDocumentMgr *m_pDocumentMgr; + ITfContext *m_pContext; + ITfContextOwnerServices *m_pContextOwnerServices; + CInputContextOwnerCallBack *m_pICOwnerCallback; + CTextEventSink *m_pTextEventSink; + CCompartmentEventSink *m_pCompEventSink1; + CCompartmentEventSink *m_pCompEventSink2; + CInputContextOwner *m_pInputContextOwner; + DWORD m_dwUnknown3[3]; + DWORD m_dwUnknown4[2]; + DWORD m_dwQueryPos; + DWORD m_dwUnknown5; + GUID m_guid; + DWORD m_dwUnknown6[11]; + BOOL m_bSelecting; + DWORD m_dwUnknown6_5; + LONG m_cCompLocks; + DWORD m_dwUnknown7[5]; + WORD m_cGuidAtoms; + WORD m_padding; + DWORD m_adwGuidAtoms[256]; + DWORD m_dwUnknown8[17]; + TfClientId m_clientId; + DWORD m_dwUnknown9; + +public: + CicInputContext( + _In_ TfClientId cliendId, + _Inout_ PCIC_LIBTHREAD pLibThread, + _In_ HIMC hIMC); + virtual ~CicInputContext() { } + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfCleanupContextSink interface + STDMETHODIMP OnCleanupContext(_In_ TfEditCookie ecWrite, _Inout_ ITfContext *pic) override; + + // ITfContextOwnerCompositionSink interface + STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk) override; + STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew) override; + STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition) override; + + // ITfCompositionSink interface + STDMETHODIMP OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) override; + + HRESULT + GetGuidAtom( + _Inout_ CicIMCLock& imcLock, + _In_ BYTE iAtom, + _Out_opt_ LPDWORD pdwGuidAtom); + + HRESULT CreateInputContext(_Inout_ ITfThreadMgr *pThreadMgr, _Inout_ CicIMCLock& imcLock); + HRESULT DestroyInputContext(); +}; diff --git a/dll/ime/msctfime/msctfime.cpp b/dll/ime/msctfime/msctfime.cpp index ccd442083ab..445998d6a9c 100644 --- a/dll/ime/msctfime/msctfime.cpp +++ b/dll/ime/msctfime/msctfime.cpp @@ -20,87 +20,31 @@ BOOL gfTFInitLib = FALSE; CRITICAL_SECTION g_csLock; CDispAttrPropCache *g_pPropCache = NULL; -DEFINE_GUID(GUID_COMPARTMENT_CTFIME_DIMFLAGS, 0xA94C5FD2, 0xC471, 0x4031, 0x95, 0x46, 0x70, 0x9C, 0x17, 0x30, 0x0C, 0xB9); -DEFINE_GUID(GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0x85A688F7, 0x6DC8, 0x4F17, 0xA8, 0x3A, 0xB1, 0x1C, 0x09, 0xCD, 0xD7, 0xBF); - EXTERN_C void __cxa_pure_virtual(void) { ERR("__cxa_pure_virtual\n"); } -UINT WM_MSIME_SERVICE = 0; -UINT WM_MSIME_UIREADY = 0; -UINT WM_MSIME_RECONVERTREQUEST = 0; -UINT WM_MSIME_RECONVERT = 0; -UINT WM_MSIME_DOCUMENTFEED = 0; -UINT WM_MSIME_QUERYPOSITION = 0; -UINT WM_MSIME_MODEBIAS = 0; -UINT WM_MSIME_SHOWIMEPAD = 0; -UINT WM_MSIME_MOUSE = 0; -UINT WM_MSIME_KEYMAP = 0; - -/// @implemented -BOOL IsMsImeMessage(_In_ UINT uMsg) -{ - return (uMsg == WM_MSIME_SERVICE || - uMsg == WM_MSIME_UIREADY || - uMsg == WM_MSIME_RECONVERTREQUEST || - uMsg == WM_MSIME_RECONVERT || - uMsg == WM_MSIME_DOCUMENTFEED || - uMsg == WM_MSIME_QUERYPOSITION || - uMsg == WM_MSIME_MODEBIAS || - uMsg == WM_MSIME_SHOWIMEPAD || - uMsg == WM_MSIME_MOUSE || - uMsg == WM_MSIME_KEYMAP); -} - -/// @implemented -BOOL RegisterMSIMEMessage(VOID) -{ - // Using ANSI (A) version here can reduce binary size. - WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); - WM_MSIME_UIREADY = RegisterWindowMessageA("MSIMEUIReady"); - WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); - WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); - WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); - WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); - WM_MSIME_MODEBIAS = RegisterWindowMessageA("MSIMEModeBias"); - WM_MSIME_SHOWIMEPAD = RegisterWindowMessageA("MSIMEShowImePad"); - WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); - WM_MSIME_KEYMAP = RegisterWindowMessageA("MSIMEKeyMap"); - return (WM_MSIME_SERVICE && - WM_MSIME_UIREADY && - WM_MSIME_RECONVERTREQUEST && - WM_MSIME_RECONVERT && - WM_MSIME_DOCUMENTFEED && - WM_MSIME_QUERYPOSITION && - WM_MSIME_MODEBIAS && - WM_MSIME_SHOWIMEPAD && - WM_MSIME_MOUSE && - WM_MSIME_KEYMAP); -} - -typedef BOOLEAN (WINAPI *FN_DllShutDownInProgress)(VOID); +typedef BOOLEAN (WINAPI *FN_DllShutdownInProgress)(VOID); /// This function calls ntdll!RtlDllShutdownInProgress. /// It can detect the system is shutting down or not. /// @implemented -EXTERN_C BOOLEAN WINAPI -DllShutDownInProgress(VOID) +EXTERN_C BOOLEAN WINAPI DllShutdownInProgress(VOID) { HMODULE hNTDLL; - static FN_DllShutDownInProgress s_fnDllShutDownInProgress = NULL; + static FN_DllShutdownInProgress s_fnDllShutdownInProgress = NULL; - if (s_fnDllShutDownInProgress) - return s_fnDllShutDownInProgress(); + if (s_fnDllShutdownInProgress) + return s_fnDllShutdownInProgress(); hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE); - s_fnDllShutDownInProgress = - (FN_DllShutDownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress"); - if (!s_fnDllShutDownInProgress) + s_fnDllShutdownInProgress = + (FN_DllShutdownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress"); + if (!s_fnDllShutdownInProgress) return FALSE; - return s_fnDllShutDownInProgress(); + return s_fnDllShutdownInProgress(); } /// This function checks if the current user logon session is interactive. @@ -195,2533 +139,115 @@ HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread) } ::LeaveCriticalSection(&g_csLock); - return hr; -} - -HIMC GetActiveContext(VOID) -{ - HWND hwndFocus = ::GetFocus(); - if (!hwndFocus) - hwndFocus = ::GetActiveWindow(); - return ::ImmGetContext(hwndFocus); -} - -/// @implemented -HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread) -{ - if (!pLibThread) - return E_FAIL; - - if (pLibThread->m_pDisplayAttrMgr) - { - pLibThread->m_pDisplayAttrMgr->Release(); - pLibThread->m_pDisplayAttrMgr = NULL; - } - - return S_OK; -} - -/// Gets the charset from a language ID. -/// @implemented -BYTE GetCharsetFromLangId(_In_ DWORD dwValue) -{ - CHARSETINFO info; - if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE)) - return 0; - return info.ciCharset; -} - -/// Selects or unselects the input context. -/// @implemented -HRESULT -InternalSelectEx( - _In_ HIMC hIMC, - _In_ BOOL fSelect, - _In_ LANGID LangID) -{ - CicIMCLock imcLock(hIMC); - if (!imcLock) - imcLock.m_hr = E_FAIL; - if (FAILED(imcLock.m_hr)) - return imcLock.m_hr; - - if (PRIMARYLANGID(LangID) == LANG_CHINESE) - { - imcLock.get().cfCandForm[0].dwStyle = 0; - imcLock.get().cfCandForm[0].dwIndex = (DWORD)-1; - } - - if (!fSelect) - { - imcLock.get().fdwInit &= ~INIT_GUIDMAP; - return imcLock.m_hr; - } - - if (!imcLock.ClearCand()) - return imcLock.m_hr; - - // Populate conversion mode - if (!(imcLock.get().fdwInit & INIT_CONVERSION)) - { - DWORD dwConv = (imcLock.get().fdwConversion & IME_CMODE_SOFTKBD); - if (LangID) - { - if (PRIMARYLANGID(LangID) == LANG_JAPANESE) - { - dwConv |= IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; - } - else if (PRIMARYLANGID(LangID) != LANG_KOREAN) - { - dwConv |= IME_CMODE_NATIVE; - } - } - imcLock.get().fdwConversion |= dwConv; - imcLock.get().fdwInit |= INIT_CONVERSION; - } - - // Populate sentence mode - imcLock.get().fdwSentence |= IME_SMODE_PHRASEPREDICT; - - // Populate LOGFONT - if (!(imcLock.get().fdwInit & INIT_LOGFONT)) - { - // Get logical font - LOGFONTW lf; - HDC hDC = ::GetDC(imcLock.get().hWnd); - HGDIOBJ hFont = GetCurrentObject(hDC, OBJ_FONT); - ::GetObjectW(hFont, sizeof(LOGFONTW), &lf); - ::ReleaseDC(imcLock.get().hWnd, hDC); - - imcLock.get().lfFont.W = lf; - imcLock.get().fdwInit |= INIT_LOGFONT; - } - imcLock.get().lfFont.W.lfCharSet = GetCharsetFromLangId(LangID); - - imcLock.InitContext(); - - return imcLock.m_hr; -} - -/*********************************************************************** - * Compartment - */ - -/// @implemented -HRESULT -GetCompartment( - IUnknown *pUnknown, - REFGUID rguid, - ITfCompartment **ppComp, - BOOL bThread) -{ - *ppComp = NULL; - - ITfThreadMgr *pThreadMgr = NULL; - ITfCompartmentMgr *pCompMgr = NULL; - - HRESULT hr; - if (bThread) - { - hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); - if (FAILED(hr)) - return hr; - - hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); - } - else - { - hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); - } - - if (SUCCEEDED(hr)) - { - hr = E_FAIL; - if (pCompMgr) - { - hr = pCompMgr->GetCompartment(rguid, ppComp); - pCompMgr->Release(); - } - } - - if (pThreadMgr) - pThreadMgr->Release(); - - return hr; -} - -/// @implemented -HRESULT -SetCompartmentDWORD( - TfEditCookie cookie, - IUnknown *pUnknown, - REFGUID rguid, - DWORD dwValue, - BOOL bThread) -{ - ITfCompartment *pComp = NULL; - HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); - if (FAILED(hr)) - return hr; - - VARIANT vari; - V_I4(&vari) = dwValue; - V_VT(&vari) = VT_I4; - hr = pComp->SetValue(cookie, &vari); - - pComp->Release(); - return hr; -} - -/// @implemented -HRESULT -GetCompartmentDWORD( - IUnknown *pUnknown, - REFGUID rguid, - LPDWORD pdwValue, - BOOL bThread) -{ - *pdwValue = 0; - - ITfCompartment *pComp = NULL; - HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); - if (FAILED(hr)) - return hr; - - VARIANT vari; - hr = pComp->GetValue(&vari); - if (hr == S_OK) - *pdwValue = V_I4(&vari); - - pComp->Release(); - return hr; -} - -/// @implemented -HRESULT -SetCompartmentUnknown( - TfEditCookie cookie, - IUnknown *pUnknown, - REFGUID rguid, - IUnknown *punkValue) -{ - ITfCompartment *pComp = NULL; - HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, FALSE); - if (FAILED(hr)) - return hr; - - VARIANT vari; - V_UNKNOWN(&vari) = punkValue; - V_VT(&vari) = VT_UNKNOWN; - hr = pComp->SetValue(cookie, &vari); - - pComp->Release(); - return hr; -} - -/// @implemented -HRESULT -ClearCompartment( - TfClientId tid, - IUnknown *pUnknown, - REFGUID rguid, - BOOL bThread) -{ - ITfCompartmentMgr *pCompMgr = NULL; - ITfThreadMgr *pThreadMgr = NULL; - - HRESULT hr; - if (bThread) - { - hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); - if (FAILED(hr)) - return hr; - - hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); - } - else - { - hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); - } - - if (SUCCEEDED(hr)) - { - hr = E_FAIL; - if (pCompMgr) - { - hr = pCompMgr->ClearCompartment(tid, rguid); - pCompMgr->Release(); - } - } - - if (pThreadMgr) - pThreadMgr->Release(); - - return hr; -} - -typedef struct CESMAP -{ - ITfCompartment *m_pComp; - DWORD m_dwCookie; -} CESMAP, *PCESMAP; - -typedef INT (CALLBACK *FN_EVENTSINK)(LPVOID, REFGUID); - -class CCompartmentEventSink : public ITfCompartmentEventSink -{ - CicArray m_array; - LONG m_cRefs; - FN_EVENTSINK m_fnEventSink; - LPVOID m_pUserData; - -public: - CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData); - virtual ~CCompartmentEventSink(); - - HRESULT _Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread); - HRESULT _Unadvise(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfCompartmentEventSink interface - STDMETHODIMP OnChange(REFGUID rguid) override; -}; - -/// @implemented -CCompartmentEventSink::CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData) - : m_array() - , m_cRefs(1) - , m_fnEventSink(fnEventSink) - , m_pUserData(pUserData) -{ -} - -/// @implemented -CCompartmentEventSink::~CCompartmentEventSink() -{ -} - -/// @implemented -STDMETHODIMP CCompartmentEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - - *ppvObj = NULL; - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CCompartmentEventSink::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CCompartmentEventSink::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -STDMETHODIMP CCompartmentEventSink::OnChange(REFGUID rguid) -{ - return m_fnEventSink(m_pUserData, rguid); -} - -/// @implemented -HRESULT -CCompartmentEventSink::_Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread) -{ - CESMAP *pCesMap = m_array.Append(1); - if (!pCesMap) - return E_OUTOFMEMORY; - - ITfSource *pSource = NULL; - - HRESULT hr = GetCompartment(pUnknown, rguid, &pCesMap->m_pComp, bThread); - if (FAILED(hr)) - { - hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); - if (FAILED(hr)) - { - hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &pCesMap->m_dwCookie); - if (FAILED(hr)) - { - if (pCesMap->m_pComp) - { - pCesMap->m_pComp->Release(); - pCesMap->m_pComp = NULL; - } - m_array.Remove(m_array.size() - 1, 1); - } - else - { - hr = S_OK; - } - } - } - - if (pSource) - pSource->Release(); - - return hr; -} - -/// @implemented -HRESULT CCompartmentEventSink::_Unadvise() -{ - CESMAP *pCesMap = m_array.data(); - size_t cItems = m_array.size(); - if (!cItems) - return S_OK; - - do - { - ITfSource *pSource = NULL; - HRESULT hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); - if (SUCCEEDED(hr)) - pSource->UnadviseSink(pCesMap->m_dwCookie); - - if (pCesMap->m_pComp) - { - pCesMap->m_pComp->Release(); - pCesMap->m_pComp = NULL; - } - - if (pSource) - pSource->Release(); - - ++pCesMap; - --cItems; - } while (cItems); - - return S_OK; -} - -class CInputContextOwnerCallBack; -class CInputContextOwner; - -typedef INT (CALLBACK *FN_ENDEDIT)(INT, LPVOID, LPVOID); -typedef INT (CALLBACK *FN_LAYOUTCHANGE)(UINT nType, FN_ENDEDIT fnEndEdit, ITfContextView *pView); - -class CTextEventSink : public ITfTextEditSink, ITfTextLayoutSink -{ -protected: - LONG m_cRefs; - IUnknown *m_pUnknown; - DWORD m_dwEditSinkCookie; - DWORD m_dwLayoutSinkCookie; - union - { - UINT m_uFlags; - FN_LAYOUTCHANGE m_fnLayoutChange; - }; - FN_ENDEDIT m_fnEndEdit; - LPVOID m_pCallbackPV; - -public: - CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV); - virtual ~CTextEventSink(); - - HRESULT _Advise(IUnknown *pUnknown, UINT uFlags); - HRESULT _Unadvise(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfTextEditSink interface - STDMETHODIMP OnEndEdit( - ITfContext *pic, - TfEditCookie ecReadOnly, - ITfEditRecord *pEditRecord) override; - - // ITfTextLayoutSink interface - STDMETHODIMP - OnLayoutChange( - ITfContext *pContext, - TfLayoutCode lcode, - ITfContextView *pContextView) override; -}; - -/// @implemented -CTextEventSink::CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV) -{ - m_cRefs = 1; - m_pUnknown = NULL; - m_dwEditSinkCookie = (DWORD)-1; - m_dwLayoutSinkCookie = (DWORD)-1; - m_fnLayoutChange = NULL; - m_fnEndEdit = fnEndEdit; - m_pCallbackPV = pCallbackPV; -} - -/// @implemented -CTextEventSink::~CTextEventSink() -{ -} - -/// @implemented -STDMETHODIMP CTextEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextEditSink)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - if (IsEqualIID(riid, IID_ITfTextLayoutSink)) - { - *ppvObj = static_cast(this); - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CTextEventSink::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CTextEventSink::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -struct TEXT_EVENT_SINK_END_EDIT -{ - TfEditCookie m_ecReadOnly; - ITfEditRecord *m_pEditRecord; - ITfContext *m_pContext; -}; - -/// @implemented -STDMETHODIMP CTextEventSink::OnEndEdit( - ITfContext *pic, - TfEditCookie ecReadOnly, - ITfEditRecord *pEditRecord) -{ - TEXT_EVENT_SINK_END_EDIT Data = { ecReadOnly, pEditRecord, pic }; - return m_fnEndEdit(1, m_pCallbackPV, (LPVOID)&Data); -} - -/// @implemented -STDMETHODIMP CTextEventSink::OnLayoutChange( - ITfContext *pContext, - TfLayoutCode lcode, - ITfContextView *pContextView) -{ - switch (lcode) - { - case TF_LC_CREATE: - return m_fnLayoutChange(3, m_fnEndEdit, pContextView); - case TF_LC_CHANGE: - return m_fnLayoutChange(2, m_fnEndEdit, pContextView); - case TF_LC_DESTROY: - return m_fnLayoutChange(4, m_fnEndEdit, pContextView); - default: - return E_INVALIDARG; - } -} - -/// @implemented -HRESULT CTextEventSink::_Advise(IUnknown *pUnknown, UINT uFlags) -{ - m_pUnknown = NULL; - m_uFlags = uFlags; - - ITfSource *pSource = NULL; - HRESULT hr = pUnknown->QueryInterface(IID_ITfSource, (void**)&pSource); - if (SUCCEEDED(hr)) - { - ITfTextEditSink *pSink = static_cast(this); - if (uFlags & 1) - hr = pSource->AdviseSink(IID_ITfTextEditSink, pSink, &m_dwEditSinkCookie); - if (SUCCEEDED(hr) && (uFlags & 2)) - hr = pSource->AdviseSink(IID_ITfTextLayoutSink, pSink, &m_dwLayoutSinkCookie); - - if (SUCCEEDED(hr)) - { - m_pUnknown = pUnknown; - pUnknown->AddRef(); - } - else - { - pSource->UnadviseSink(m_dwEditSinkCookie); - } - } - - if (pSource) - pSource->Release(); - - return hr; -} - -/// @implemented -HRESULT CTextEventSink::_Unadvise() -{ - if (!m_pUnknown) - return E_FAIL; - - ITfSource *pSource = NULL; - HRESULT hr = m_pUnknown->QueryInterface(IID_ITfSource, (void**)&pSource); - if (SUCCEEDED(hr)) - { - if (m_uFlags & 1) - hr = pSource->UnadviseSink(m_dwEditSinkCookie); - if (m_uFlags & 2) - hr = pSource->UnadviseSink(m_dwLayoutSinkCookie); - - pSource->Release(); - } - - m_pUnknown->Release(); - m_pUnknown = NULL; - - return E_NOTIMPL; -} - -/*********************************************************************** - * CicInputContext - * - * The msctfime.ime's input context. - */ -class CicInputContext - : public ITfCleanupContextSink - , public ITfContextOwnerCompositionSink - , public ITfCompositionSink -{ -public: - LONG m_cRefs; - HIMC m_hIMC; - ITfDocumentMgr *m_pDocumentMgr; - ITfContext *m_pContext; - ITfContextOwnerServices *m_pContextOwnerServices; - CInputContextOwnerCallBack *m_pICOwnerCallback; - CTextEventSink *m_pTextEventSink; - CCompartmentEventSink *m_pCompEventSink1; - CCompartmentEventSink *m_pCompEventSink2; - CInputContextOwner *m_pInputContextOwner; - DWORD m_dwUnknown3[3]; - DWORD m_dwUnknown4[2]; - DWORD m_dwQueryPos; - DWORD m_dwUnknown5; - GUID m_guid; - DWORD m_dwUnknown6[11]; - BOOL m_bSelecting; - DWORD m_dwUnknown6_5; - LONG m_cCompLocks; - DWORD m_dwUnknown7[5]; - WORD m_cGuidAtoms; - WORD m_padding; - DWORD m_adwGuidAtoms[256]; - DWORD m_dwUnknown8[17]; - TfClientId m_clientId; - DWORD m_dwUnknown9; - -public: - CicInputContext( - _In_ TfClientId cliendId, - _Inout_ PCIC_LIBTHREAD pLibThread, - _In_ HIMC hIMC); - virtual ~CicInputContext() { } - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfCleanupContextSink interface - STDMETHODIMP OnCleanupContext(_In_ TfEditCookie ecWrite, _Inout_ ITfContext *pic) override; - - // ITfContextOwnerCompositionSink interface - STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk) override; - STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew) override; - STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition) override; - - // ITfCompositionSink interface - STDMETHODIMP OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) override; - - HRESULT - GetGuidAtom( - _Inout_ CicIMCLock& imcLock, - _In_ BYTE iAtom, - _Out_opt_ LPDWORD pdwGuidAtom); - - HRESULT CreateInputContext(_Inout_ ITfThreadMgr *pThreadMgr, _Inout_ CicIMCLock& imcLock); - HRESULT DestroyInputContext(); -}; - -/// @unimplemented -CicInputContext::CicInputContext( - _In_ TfClientId cliendId, - _Inout_ PCIC_LIBTHREAD pLibThread, - _In_ HIMC hIMC) -{ - m_hIMC = hIMC; - m_guid = GUID_NULL; - m_dwQueryPos = 0; - m_cRefs = 1; -} - -/// @implemented -STDMETHODIMP CicInputContext::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - *ppvObj = NULL; - - if (IsEqualIID(riid, IID_ITfContextOwnerCompositionSink)) - { - *ppvObj = static_cast(this); - AddRef(); - return S_OK; - } - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCleanupContextSink)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CicInputContext::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CicInputContext::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -STDMETHODIMP -CicInputContext::OnStartComposition( - ITfCompositionView *pComposition, - BOOL *pfOk) -{ - if ((m_cCompLocks <= 0) || m_dwUnknown6_5) - { - *pfOk = TRUE; - ++m_cCompLocks; - } - else - { - *pfOk = FALSE; - } - return S_OK; -} - -/// @implemented -STDMETHODIMP -CicInputContext::OnUpdateComposition( - ITfCompositionView *pComposition, - ITfRange *pRangeNew) -{ - return S_OK; -} - -/// @implemented -STDMETHODIMP -CicInputContext::OnEndComposition( - ITfCompositionView *pComposition) -{ - --m_cCompLocks; - return S_OK; -} - -/// @implemented -HRESULT -CicInputContext::GetGuidAtom( - _Inout_ CicIMCLock& imcLock, - _In_ BYTE iAtom, - _Out_opt_ LPDWORD pdwGuidAtom) -{ - CicIMCCLock imeContext(imcLock.get().hCompStr); - HRESULT hr = imeContext.m_hr; - if (!imeContext) - hr = E_FAIL; - if (FAILED(hr)) - return hr; - - hr = E_FAIL; - if (iAtom < m_cGuidAtoms) - { - *pdwGuidAtom = m_adwGuidAtoms[iAtom]; - hr = S_OK; - } - - return hr; -} - -/// @unimplemented -HRESULT -CicInputContext::CreateInputContext( - _Inout_ ITfThreadMgr *pThreadMgr, - _Inout_ CicIMCLock& imcLock) -{ - //FIXME - return E_NOTIMPL; -} - -/// @unimplemented -HRESULT -CicInputContext::DestroyInputContext() -{ - ITfSourceSingle *pSource = NULL; - - if (m_pContext && m_pContext->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) - pSource->UnadviseSingleSink(m_clientId, IID_ITfCleanupContextSink); - - //FIXME: m_dwUnknown5 - - if (m_pTextEventSink) - { - m_pTextEventSink->_Unadvise(); - m_pTextEventSink->Release(); - m_pTextEventSink = NULL; - } - - if (m_pCompEventSink2) - { - m_pCompEventSink2->_Unadvise(); - m_pCompEventSink2->Release(); - m_pCompEventSink2 = NULL; - } - - if (m_pCompEventSink1) - { - m_pCompEventSink1->_Unadvise(); - m_pCompEventSink1->Release(); - m_pCompEventSink1 = NULL; - } - - //FIXME: m_pInputContextOwner - - if (m_pDocumentMgr) - m_pDocumentMgr->Pop(1); - - if (m_pContext) - { - ClearCompartment(m_clientId, m_pContext, GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0); - m_pContext->Release(); - m_pContext = NULL; - } - - if (m_pContextOwnerServices) - { - m_pContextOwnerServices->Release(); - m_pContextOwnerServices = NULL; - } - - // FIXME: m_pICOwnerCallback - - if (m_pDocumentMgr) - { - m_pDocumentMgr->Release(); - m_pDocumentMgr = NULL; - } - - if (pSource) - pSource->Release(); - - return S_OK; -} - -/// @implemented -STDMETHODIMP -CicInputContext::OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) -{ - return S_OK; -} - -/// Retrieves the IME information. -/// @implemented -HRESULT -Inquire( - _Out_ LPIMEINFO lpIMEInfo, - _Out_ LPWSTR lpszWndClass, - _In_ DWORD dwSystemInfoFlags, - _In_ HKL hKL) -{ - if (!lpIMEInfo) - return E_OUTOFMEMORY; - - StringCchCopyW(lpszWndClass, 64, L"MSCTFIME UI"); - lpIMEInfo->dwPrivateDataSize = 0; - - switch (LOWORD(hKL)) // Language ID - { - case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): // Japanese - { - lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | - IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | - IME_PROP_KBD_CHAR_FIRST; - lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_KATAKANA | - IME_CMODE_NATIVE; - lpIMEInfo->fdwSentenceCaps = IME_SMODE_CONVERSATION | IME_SMODE_PLAURALCLAUSE; - lpIMEInfo->fdwSelectCaps = SELECT_CAP_SENTENCE | SELECT_CAP_CONVERSION; - lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | - SCS_CAP_COMPSTR; - lpIMEInfo->fdwUICaps = UI_CAP_ROT90; - break; - } - case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): // Korean - { - lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | - IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | - IME_PROP_KBD_CHAR_FIRST; - lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; - lpIMEInfo->fdwSentenceCaps = 0; - lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_COMPSTR; - lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; - lpIMEInfo->fdwUICaps = UI_CAP_ROT90; - break; - } - case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): // Simplified Chinese - case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): // Traditional Chinese - { - lpIMEInfo->fdwProperty = IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | - IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; - lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; - lpIMEInfo->fdwSentenceCaps = SELECT_CAP_CONVERSION; - lpIMEInfo->fdwSelectCaps = 0; - lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | - SCS_CAP_COMPSTR; - lpIMEInfo->fdwUICaps = UI_CAP_ROT90; - break; - } - default: // Otherwise - { - lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; - lpIMEInfo->fdwConversionCaps = 0; - lpIMEInfo->fdwSentenceCaps = 0; - lpIMEInfo->fdwSCSCaps = 0; - lpIMEInfo->fdwUICaps = 0; - lpIMEInfo->fdwSelectCaps = 0; - break; - } - } - - return S_OK; -} - -class TLS; - -typedef INT (CALLBACK *FN_INITDOCMGR)(UINT, ITfDocumentMgr *, ITfDocumentMgr *, LPVOID); -typedef INT (CALLBACK *FN_PUSHPOP)(UINT, ITfContext *, LPVOID); - -class CThreadMgrEventSink : public ITfThreadMgrEventSink -{ -protected: - ITfThreadMgr *m_pThreadMgr; - DWORD m_dwCookie; - FN_INITDOCMGR m_fnInit; - FN_PUSHPOP m_fnPushPop; - DWORD m_dw; - LPVOID m_pCallbackPV; - LONG m_cRefs; - -public: - CThreadMgrEventSink( - _In_ FN_INITDOCMGR fnInit, - _In_ FN_PUSHPOP fnPushPop = NULL, - _Inout_ LPVOID pvCallbackPV = NULL); - virtual ~CThreadMgrEventSink() { } - - void SetCallbackPV(_Inout_ LPVOID pv); - HRESULT _Advise(ITfThreadMgr *pThreadMgr); - HRESULT _Unadvise(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfThreadMgrEventSink interface - STDMETHODIMP OnInitDocumentMgr(ITfDocumentMgr *pdim) override; - STDMETHODIMP OnUninitDocumentMgr(ITfDocumentMgr *pdim) override; - STDMETHODIMP OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) override; - STDMETHODIMP OnPushContext(ITfContext *pic) override; - STDMETHODIMP OnPopContext(ITfContext *pic) override; - - static INT CALLBACK DIMCallback( - UINT nCode, - ITfDocumentMgr *pDocMgr1, - ITfDocumentMgr *pDocMgr2, - LPVOID pUserData); -}; - -/// @implemented -CThreadMgrEventSink::CThreadMgrEventSink( - _In_ FN_INITDOCMGR fnInit, - _In_ FN_PUSHPOP fnPushPop, - _Inout_ LPVOID pvCallbackPV) -{ - m_fnInit = fnInit; - m_fnPushPop = fnPushPop; - m_pCallbackPV = pvCallbackPV; - m_cRefs = 1; -} - -/// @implemented -STDMETHODIMP CThreadMgrEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfThreadMgrEventSink)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - *ppvObj = NULL; - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CThreadMgrEventSink::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CThreadMgrEventSink::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -INT CALLBACK -CThreadMgrEventSink::DIMCallback( - UINT nCode, - ITfDocumentMgr *pDocMgr1, - ITfDocumentMgr *pDocMgr2, - LPVOID pUserData) -{ - return E_NOTIMPL; -} - -STDMETHODIMP CThreadMgrEventSink::OnInitDocumentMgr(ITfDocumentMgr *pdim) -{ - if (!m_fnInit) - return S_OK; - return m_fnInit(0, pdim, NULL, m_pCallbackPV); -} - -STDMETHODIMP CThreadMgrEventSink::OnUninitDocumentMgr(ITfDocumentMgr *pdim) -{ - if (!m_fnInit) - return S_OK; - return m_fnInit(1, pdim, NULL, m_pCallbackPV); -} - -STDMETHODIMP -CThreadMgrEventSink::OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) -{ - if (!m_fnInit) - return S_OK; - return m_fnInit(2, pdimFocus, pdimPrevFocus, m_pCallbackPV); -} - -STDMETHODIMP CThreadMgrEventSink::OnPushContext(ITfContext *pic) -{ - if (!m_fnPushPop) - return S_OK; - return m_fnPushPop(3, pic, m_pCallbackPV); -} - -STDMETHODIMP CThreadMgrEventSink::OnPopContext(ITfContext *pic) -{ - if (!m_fnPushPop) - return S_OK; - return m_fnPushPop(4, pic, m_pCallbackPV); -} - -void CThreadMgrEventSink::SetCallbackPV(_Inout_ LPVOID pv) -{ - if (!m_pCallbackPV) - m_pCallbackPV = pv; -} - -HRESULT CThreadMgrEventSink::_Advise(ITfThreadMgr *pThreadMgr) -{ - m_pThreadMgr = NULL; - - HRESULT hr = E_FAIL; - ITfSource *pSource = NULL; - if (pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && - pSource->AdviseSink(IID_ITfThreadMgrEventSink, this, &m_dwCookie) == S_OK) - { - m_pThreadMgr = pThreadMgr; - pThreadMgr->AddRef(); - hr = S_OK; - } - - if (pSource) - pSource->Release(); - - return hr; -} - -HRESULT CThreadMgrEventSink::_Unadvise() -{ - HRESULT hr = E_FAIL; - ITfSource *pSource = NULL; - - if (m_pThreadMgr) - { - if (m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && - pSource->UnadviseSink(m_dwCookie) == S_OK) - { - hr = S_OK; - } - - if (pSource) - pSource->Release(); - } - - if (m_pThreadMgr) - { - m_pThreadMgr->Release(); - m_pThreadMgr = NULL; - } - - return hr; -} - -class CFunctionProviderBase : public ITfFunctionProvider -{ -protected: - TfClientId m_clientId; - GUID m_guid; - BSTR m_bstr; - LONG m_cRefs; - -public: - CFunctionProviderBase(_In_ TfClientId clientId); - virtual ~CFunctionProviderBase(); - - // IUnknown interface - STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfFunctionProvider interface - STDMETHODIMP GetType(_Out_ GUID *guid) override; - STDMETHODIMP GetDescription(_Out_ BSTR *desc) override; - //STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) = 0; - - BOOL Init(_In_ REFGUID rguid, _In_ LPCWSTR psz); -}; - -/// @implemented -CFunctionProviderBase::CFunctionProviderBase(_In_ TfClientId clientId) -{ - m_clientId = clientId; - m_guid = GUID_NULL; - m_bstr = NULL; - m_cRefs = 1; -} - -/// @implemented -CFunctionProviderBase::~CFunctionProviderBase() -{ - if (!RtlDllShutdownInProgress()) - ::SysFreeString(m_bstr); -} - -/// @implemented -BOOL -CFunctionProviderBase::Init( - _In_ REFGUID rguid, - _In_ LPCWSTR psz) -{ - m_bstr = ::SysAllocString(psz); - m_guid = rguid; - return (m_bstr != NULL); -} - -class CFnDocFeed : public IAImmFnDocFeed -{ - LONG m_cRefs; - -public: - CFnDocFeed(); - virtual ~CFnDocFeed(); - - // IUnknown interface - STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // IAImmFnDocFeed interface - STDMETHODIMP DocFeed() override; - STDMETHODIMP ClearDocFeedBuffer() override; - STDMETHODIMP StartReconvert() override; - STDMETHODIMP StartUndoCompositionString() override; -}; - -CFnDocFeed::CFnDocFeed() -{ - m_cRefs = 1; -} - -CFnDocFeed::~CFnDocFeed() -{ -} - -/// @implemented -STDMETHODIMP CFnDocFeed::QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IAImmFnDocFeed)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CFnDocFeed::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CFnDocFeed::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @unimplemented -STDMETHODIMP CFnDocFeed::DocFeed() -{ - return E_NOTIMPL; -} - -/// @unimplemented -STDMETHODIMP CFnDocFeed::ClearDocFeedBuffer() -{ - return E_NOTIMPL; -} - -/// @unimplemented -STDMETHODIMP CFnDocFeed::StartReconvert() -{ - return E_NOTIMPL; -} - -/// @unimplemented -STDMETHODIMP CFnDocFeed::StartUndoCompositionString() -{ - return E_NOTIMPL; -} - -/// @implemented -STDMETHODIMP -CFunctionProviderBase::QueryInterface( - _In_ REFIID riid, - _Out_ LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfFunctionProvider)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CFunctionProviderBase::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CFunctionProviderBase::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -STDMETHODIMP CFunctionProviderBase::GetType(_Out_ GUID *guid) -{ - *guid = m_guid; - return S_OK; -} - -/// @implemented -STDMETHODIMP CFunctionProviderBase::GetDescription(_Out_ BSTR *desc) -{ - *desc = ::SysAllocString(m_bstr); - return (*desc ? S_OK : E_OUTOFMEMORY); -} - -class CFunctionProvider : public CFunctionProviderBase -{ -public: - CFunctionProvider(_In_ TfClientId clientId); - - STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) override; -}; - -/// @implemented -CFunctionProvider::CFunctionProvider(_In_ TfClientId clientId) : CFunctionProviderBase(clientId) -{ - Init(CLSID_CAImmLayer, L"MSCTFIME::Function Provider"); -} - -/// @implemented -STDMETHODIMP -CFunctionProvider::GetFunction( - _In_ REFGUID guid, - _In_ REFIID riid, - _Out_ IUnknown **func) -{ - *func = NULL; - - if (IsEqualGUID(guid, GUID_NULL) && - IsEqualIID(riid, IID_IAImmFnDocFeed)) - { - *func = new(cicNoThrow) CFnDocFeed(); - if (*func) - return S_OK; - } - - return E_NOINTERFACE; -} - -/* FIXME */ -class CicBridge : public ITfSysHookSink -{ -protected: - LONG m_cRefs; - BOOL m_bImmxInited; - BOOL m_bUnknown1; - BOOL m_bDeactivating; - DWORD m_cActivateLocks; - ITfKeystrokeMgr *m_pKeystrokeMgr; - ITfDocumentMgr *m_pDocMgr; - CThreadMgrEventSink *m_pThreadMgrEventSink; - TfClientId m_cliendId; - CIC_LIBTHREAD m_LibThread; - BOOL m_bUnknown2; - - static BOOL CALLBACK EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam); - static BOOL CALLBACK EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam); - -public: - CicBridge(); - virtual ~CicBridge(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfSysHookSink interface - STDMETHODIMP OnPreFocusDIM(HWND hwnd) override; - STDMETHODIMP OnSysKeyboardProc(UINT, LONG) override; - STDMETHODIMP OnSysShellProc(INT, UINT, LONG) override; - - HRESULT InitIMMX(_Inout_ TLS *pTLS); - BOOL UnInitIMMX(_Inout_ TLS *pTLS); - HRESULT ActivateIMMX(_Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr); - HRESULT DeactivateIMMX(_Inout_ TLS *pTLS, _Inout_ ITfThreadMgr_P *pThreadMgr); - - HRESULT CreateInputContext(TLS *pTLS, HIMC hIMC); - HRESULT DestroyInputContext(TLS *pTLS, HIMC hIMC); - ITfContext *GetInputContext(CicIMCCLock& imeContext); - - HRESULT SelectEx( - _Inout_ TLS *pTLS, - _Inout_ ITfThreadMgr_P *pThreadMgr, - _In_ HIMC hIMC, - _In_ BOOL fSelect, - _In_ HKL hKL); - HRESULT OnSetOpenStatus( - TLS *pTLS, - ITfThreadMgr_P *pThreadMgr, - CicIMCLock& imcLock, - CicInputContext *pCicIC); - - void PostTransMsg(_In_ HWND hWnd, _In_ INT cTransMsgs, _In_ const TRANSMSG *pTransMsgs); - void GetDocumentManager(_Inout_ CicIMCCLock& imeContext); - - HRESULT - ConfigureGeneral(_Inout_ TLS* pTLS, - _In_ ITfThreadMgr *pThreadMgr, - _In_ HKL hKL, - _In_ HWND hWnd); - HRESULT ConfigureRegisterWord( - _Inout_ TLS* pTLS, - _In_ ITfThreadMgr *pThreadMgr, - _In_ HKL hKL, - _In_ HWND hWnd, - _Inout_opt_ LPVOID lpData); -}; - -class CActiveLanguageProfileNotifySink : public ITfActiveLanguageProfileNotifySink -{ -protected: - typedef INT (CALLBACK *FN_COMPARE)(REFGUID rguid1, REFGUID rguid2, BOOL fActivated, LPVOID pUserData); - LONG m_cRefs; - ITfThreadMgr *m_pThreadMgr; - DWORD m_dwConnection; - FN_COMPARE m_fnCompare; - LPVOID m_pUserData; - -public: - CActiveLanguageProfileNotifySink(_In_ FN_COMPARE fnCompare, _Inout_opt_ void *pUserData); - virtual ~CActiveLanguageProfileNotifySink(); - - HRESULT _Advise(ITfThreadMgr *pThreadMgr); - HRESULT _Unadvise(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - // ITfActiveLanguageProfileNotifySink interface - STDMETHODIMP - OnActivated( - REFCLSID clsid, - REFGUID guidProfile, - BOOL fActivated) override; -}; - -/// @implemented -CActiveLanguageProfileNotifySink::CActiveLanguageProfileNotifySink( - _In_ FN_COMPARE fnCompare, - _Inout_opt_ void *pUserData) -{ - m_dwConnection = (DWORD)-1; - m_fnCompare = fnCompare; - m_cRefs = 1; - m_pUserData = pUserData; -} - -/// @implemented -CActiveLanguageProfileNotifySink::~CActiveLanguageProfileNotifySink() -{ -} - -/// @implemented -STDMETHODIMP CActiveLanguageProfileNotifySink::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink)) - { - *ppvObj = this; - AddRef(); - return S_OK; - } - *ppvObj = NULL; - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -STDMETHODIMP -CActiveLanguageProfileNotifySink::OnActivated( - REFCLSID clsid, - REFGUID guidProfile, - BOOL fActivated) -{ - if (!m_fnCompare) - return 0; - - return m_fnCompare(clsid, guidProfile, fActivated, m_pUserData); -} - -/// @implemented -HRESULT -CActiveLanguageProfileNotifySink::_Advise( - ITfThreadMgr *pThreadMgr) -{ - m_pThreadMgr = NULL; - - ITfSource *pSource = NULL; - HRESULT hr = pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); - if (FAILED(hr)) - return E_FAIL; - - hr = pSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, this, &m_dwConnection); - if (SUCCEEDED(hr)) - { - m_pThreadMgr = pThreadMgr; - pThreadMgr->AddRef(); - hr = S_OK; - } - else - { - hr = E_FAIL; - } - - if (pSource) - pSource->Release(); - - return hr; -} - -/// @implemented -HRESULT -CActiveLanguageProfileNotifySink::_Unadvise() -{ - if (!m_pThreadMgr) - return E_FAIL; - - ITfSource *pSource = NULL; - HRESULT hr = m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); - if (SUCCEEDED(hr)) - { - hr = pSource->UnadviseSink(m_dwConnection); - if (SUCCEEDED(hr)) - hr = S_OK; - } - - if (pSource) - pSource->Release(); - - if (m_pThreadMgr) - { - m_pThreadMgr->Release(); - m_pThreadMgr = NULL; - } - - return hr; -} - -/* FIXME */ -class CicProfile : public IUnknown -{ -protected: - ITfInputProcessorProfiles *m_pIPProfiles; - CActiveLanguageProfileNotifySink *m_pActiveLanguageProfileNotifySink; - LANGID m_LangID1; - WORD m_padding1; - DWORD m_dwFlags; - UINT m_nCodePage; - LANGID m_LangID2; - WORD m_padding2; - DWORD m_dwUnknown1; - LONG m_cRefs; - - static INT CALLBACK - ActiveLanguageProfileNotifySinkCallback( - REFGUID rguid1, - REFGUID rguid2, - BOOL fActivated, - LPVOID pUserData); - -public: - CicProfile(); - virtual ~CicProfile(); - - // IUnknown interface - STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; - STDMETHODIMP_(ULONG) AddRef() override; - STDMETHODIMP_(ULONG) Release() override; - - HRESULT - GetActiveLanguageProfile( - _In_ HKL hKL, - _In_ REFGUID rguid, - _Out_ TF_LANGUAGEPROFILE *pProfile); - HRESULT GetLangId(_Out_ LANGID *pLangID); - HRESULT GetCodePageA(_Out_ UINT *puCodePage); - - HRESULT InitProfileInstance(_Inout_ TLS *pTLS); -}; - -/// @implemented -CicProfile::CicProfile() -{ - m_dwFlags &= 0xFFFFFFF0; - m_cRefs = 1; - m_pIPProfiles = NULL; - m_pActiveLanguageProfileNotifySink = NULL; - m_LangID1 = 0; - m_nCodePage = CP_ACP; - m_LangID2 = 0; - m_dwUnknown1 = 0; -} - -/// @implemented -CicProfile::~CicProfile() -{ - if (m_pIPProfiles) - { - if (m_LangID1) - m_pIPProfiles->ChangeCurrentLanguage(m_LangID1); - - m_pIPProfiles->Release(); - m_pIPProfiles = NULL; - } - - if (m_pActiveLanguageProfileNotifySink) - { - m_pActiveLanguageProfileNotifySink->_Unadvise(); - m_pActiveLanguageProfileNotifySink->Release(); - m_pActiveLanguageProfileNotifySink = NULL; - } -} - -/// @implemented -STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - *ppvObj = NULL; - return E_NOINTERFACE; -} - -/// @implemented -STDMETHODIMP_(ULONG) CicProfile::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CicProfile::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -INT CALLBACK -CicProfile::ActiveLanguageProfileNotifySinkCallback( - REFGUID rguid1, - REFGUID rguid2, - BOOL fActivated, - LPVOID pUserData) -{ - CicProfile *pThis = (CicProfile *)pUserData; - pThis->m_dwFlags &= ~0xE; - return 0; -} - -/// @implemented -HRESULT CicProfile::GetCodePageA(_Out_ UINT *puCodePage) -{ - if (!puCodePage) - return E_INVALIDARG; - - if (m_dwFlags & 2) - { - *puCodePage = m_nCodePage; - return S_OK; - } - - *puCodePage = 0; - - LANGID LangID; - HRESULT hr = GetLangId(&LangID); - if (FAILED(hr)) - return E_FAIL; - - WCHAR szBuff[12]; - INT cch = ::GetLocaleInfoW(LangID, LOCALE_IDEFAULTANSICODEPAGE, szBuff, _countof(szBuff)); - if (cch) - { - szBuff[cch] = 0; - m_nCodePage = *puCodePage = wcstoul(szBuff, NULL, 10); - m_dwFlags |= 2; - } - - return S_OK; -} - -/// @implemented -HRESULT CicProfile::GetLangId(_Out_ LANGID *pLangID) -{ - *pLangID = 0; - - if (!m_pIPProfiles) - return E_FAIL; - - if (m_dwFlags & 4) - { - *pLangID = m_LangID2; - return S_OK; - } - - HRESULT hr = m_pIPProfiles->GetCurrentLanguage(pLangID); - if (SUCCEEDED(hr)) - { - m_dwFlags |= 4; - m_LangID2 = *pLangID; - } - - return hr; -} - -class TLS -{ -public: - static DWORD s_dwTlsIndex; - - DWORD m_dwSystemInfoFlags; - CicBridge *m_pBridge; - CicProfile *m_pProfile; - ITfThreadMgr_P *m_pThreadMgr; - DWORD m_dwFlags1; - DWORD m_dwFlags2; - DWORD m_dwUnknown2; - BOOL m_bDestroyed; - DWORD m_dwNowOpening; - DWORD m_NonEAComposition; - DWORD m_cWnds; - - /** - * @implemented - */ - static BOOL Initialize() - { - s_dwTlsIndex = ::TlsAlloc(); - return s_dwTlsIndex != (DWORD)-1; - } - - /** - * @implemented - */ - static VOID Uninitialize() - { - if (s_dwTlsIndex != (DWORD)-1) - { - ::TlsFree(s_dwTlsIndex); - s_dwTlsIndex = (DWORD)-1; - } - } - - /** - * @implemented - */ - static TLS* GetTLS() - { - if (s_dwTlsIndex == (DWORD)-1) - return NULL; - - return InternalAllocateTLS(); - } - - /** - * @implemented - */ - static TLS* PeekTLS() - { - return (TLS*)::TlsGetValue(TLS::s_dwTlsIndex); - } - - static TLS* InternalAllocateTLS(); - static BOOL InternalDestroyTLS(); - -}; - -DWORD TLS::s_dwTlsIndex = (DWORD)-1; - -/// @implemented -TLS* TLS::InternalAllocateTLS() -{ - TLS *pTLS = TLS::PeekTLS(); - if (pTLS) - return pTLS; - - if (DllShutDownInProgress()) - return NULL; - - pTLS = (TLS *)cicMemAllocClear(sizeof(TLS)); - if (!pTLS) - return NULL; - - if (!::TlsSetValue(s_dwTlsIndex, pTLS)) - { - cicMemFree(pTLS); - return NULL; - } - - pTLS->m_dwFlags1 |= 1; - pTLS->m_dwUnknown2 |= 1; - return pTLS; -} - -/// @implemented -BOOL TLS::InternalDestroyTLS() -{ - TLS *pTLS = TLS::PeekTLS(); - if (!pTLS) - return FALSE; - - if (pTLS->m_pBridge) - pTLS->m_pBridge->Release(); - if (pTLS->m_pProfile) - pTLS->m_pProfile->Release(); - if (pTLS->m_pThreadMgr) - pTLS->m_pThreadMgr->Release(); - - cicMemFree(pTLS); - ::TlsSetValue(s_dwTlsIndex, NULL); - return TRUE; -} - -/// @implemented -HRESULT -CicProfile::InitProfileInstance(_Inout_ TLS *pTLS) -{ - HRESULT hr = TF_CreateInputProcessorProfiles(&m_pIPProfiles); - if (FAILED(hr)) - return hr; - - if (!m_pActiveLanguageProfileNotifySink) - { - CActiveLanguageProfileNotifySink *pSink = - new(cicNoThrow) CActiveLanguageProfileNotifySink( - CicProfile::ActiveLanguageProfileNotifySinkCallback, this); - if (!pSink) - { - m_pIPProfiles->Release(); - m_pIPProfiles = NULL; - return E_FAIL; - } - m_pActiveLanguageProfileNotifySink = pSink; - } - - if (pTLS->m_pThreadMgr) - m_pActiveLanguageProfileNotifySink->_Advise(pTLS->m_pThreadMgr); - - return hr; -} - -/// @implemented -STDMETHODIMP -CicInputContext::OnCleanupContext( - _In_ TfEditCookie ecWrite, - _Inout_ ITfContext *pic) -{ - TLS *pTLS = TLS::PeekTLS(); - if (!pTLS || !pTLS->m_pProfile) - return E_OUTOFMEMORY; - - LANGID LangID; - pTLS->m_pProfile->GetLangId(&LangID); - - IMEINFO IMEInfo; - WCHAR szPath[MAX_PATH]; - if (Inquire(&IMEInfo, szPath, 0, (HKL)UlongToHandle(LangID)) != S_OK) - return E_FAIL; - - ITfProperty *pProp = NULL; - if (!(IMEInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)) - return S_OK; - - HRESULT hr = pic->GetProperty(GUID_PROP_COMPOSING, &pProp); - if (FAILED(hr)) - return S_OK; - - IEnumTfRanges *pRanges = NULL; - hr = pProp->EnumRanges(ecWrite, &pRanges, NULL); - if (SUCCEEDED(hr)) - { - ITfRange *pRange = NULL; - while (pRanges->Next(1, &pRange, 0) == S_OK) - { - VARIANT vari; - V_VT(&vari) = VT_EMPTY; - pProp->GetValue(ecWrite, pRange, &vari); - if (V_VT(&vari) == VT_I4) - { - if (V_I4(&vari)) - pProp->Clear(ecWrite, pRange); - } - pRange->Release(); - pRange = NULL; - } - pRanges->Release(); - } - pProp->Release(); - - return S_OK; -} - -/*********************************************************************** - * CicBridge - */ - -CicBridge::CicBridge() -{ - m_bImmxInited = FALSE; - m_bUnknown1 = FALSE; - m_bDeactivating = FALSE; - m_bUnknown2 = FALSE; - m_pKeystrokeMgr = NULL; - m_pDocMgr = NULL; - m_pThreadMgrEventSink = NULL; - m_cliendId = 0; - m_cRefs = 1; -} - -/// @implemented -STDMETHODIMP CicBridge::QueryInterface(REFIID riid, LPVOID* ppvObj) -{ - *ppvObj = NULL; - - if (!IsEqualIID(riid, IID_ITfSysHookSink)) - return E_NOINTERFACE; - - *ppvObj = this; - AddRef(); - - return S_OK; -} - -/// @implemented -STDMETHODIMP_(ULONG) CicBridge::AddRef() -{ - return ::InterlockedIncrement(&m_cRefs); -} - -/// @implemented -STDMETHODIMP_(ULONG) CicBridge::Release() -{ - if (::InterlockedDecrement(&m_cRefs) == 0) - { - delete this; - return 0; - } - return m_cRefs; -} - -/// @implemented -CicBridge::~CicBridge() -{ - TLS *pTLS = TLS::PeekTLS(); - if (!pTLS || !pTLS->m_pThreadMgr) - return; - - if (SUCCEEDED(DeactivateIMMX(pTLS, pTLS->m_pThreadMgr))) - UnInitIMMX(pTLS); -} - -void CicBridge::GetDocumentManager(_Inout_ CicIMCCLock& imeContext) -{ - CicInputContext *pCicIC = imeContext.get().m_pCicIC; - if (pCicIC) - { - m_pDocMgr = pCicIC->m_pDocumentMgr; - m_pDocMgr->AddRef(); - } - else - { - m_pDocMgr->Release(); - m_pDocMgr = NULL; - } -} - -/// @unimplemented -HRESULT -CicBridge::CreateInputContext( - _Inout_ TLS *pTLS, - _In_ HIMC hIMC) -{ - CicIMCLock imcLock(hIMC); - HRESULT hr = imcLock.m_hr; - if (!imcLock) - hr = E_FAIL; - if (FAILED(hr)) - return hr; - - if (!imcLock.get().hCtfImeContext) - { - HIMCC hCtfImeContext = ImmCreateIMCC(sizeof(CTFIMECONTEXT)); - if (!hCtfImeContext) - return E_OUTOFMEMORY; - imcLock.get().hCtfImeContext = hCtfImeContext; - } - - CicIMCCLock imeContext(imcLock.get().hCtfImeContext); - CicInputContext *pCicIC = imeContext.get().m_pCicIC; - if (!pCicIC) - { - pCicIC = new(cicNoThrow) CicInputContext(m_cliendId, &m_LibThread, hIMC); - if (!pCicIC) - { - imeContext.unlock(); - imcLock.unlock(); - DestroyInputContext(pTLS, hIMC); - return E_OUTOFMEMORY; - } - - if (!pTLS->m_pThreadMgr) - { - pCicIC->Release(); - imeContext.unlock(); - imcLock.unlock(); - DestroyInputContext(pTLS, hIMC); - return E_NOINTERFACE; - } - - imeContext.get().m_pCicIC = pCicIC; - } - - hr = pCicIC->CreateInputContext(pTLS->m_pThreadMgr, imcLock); - if (FAILED(hr)) - { - pCicIC->Release(); - imeContext.get().m_pCicIC = NULL; - } - else - { - if (imcLock.get().hWnd && imcLock.get().hWnd == ::GetFocus()) - { - GetDocumentManager(imeContext); - //FIXME - } - } - - return E_NOTIMPL; -} - -/// @implemented -HRESULT CicBridge::DestroyInputContext(TLS *pTLS, HIMC hIMC) -{ - CicIMCLock imcLock(hIMC); - HRESULT hr = imcLock.m_hr; - if (!imcLock) - hr = E_FAIL; - if (FAILED(hr)) - return hr; - - hr = E_FAIL; - CicIMCCLock imeContext(imcLock.get().hCtfImeContext); - if (imeContext) - hr = imeContext.m_hr; - - if (SUCCEEDED(hr) && !(imeContext.get().m_dwCicFlags & 1)) - { - imeContext.get().m_dwCicFlags |= 1; - - CicInputContext *pCicIC = imeContext.get().m_pCicIC; - if (pCicIC) - { - imeContext.get().m_pCicIC = NULL; - hr = pCicIC->DestroyInputContext(); - pCicIC->Release(); - imeContext.get().m_pCicIC = NULL; - } - } - - if (imcLock.get().hCtfImeContext) - { - ImmDestroyIMCC(imcLock.get().hCtfImeContext); - imcLock.get().hCtfImeContext = NULL; - hr = S_OK; - } - - return hr; -} - -ITfContext * -CicBridge::GetInputContext(CicIMCCLock& imeContext) -{ - CicInputContext *pCicIC = imeContext.get().m_pCicIC; - if (!pCicIC) - return NULL; - return pCicIC->m_pContext; -} - -/// @unimplemented -HRESULT CicBridge::OnSetOpenStatus( - TLS *pTLS, - ITfThreadMgr_P *pThreadMgr, - CicIMCLock& imcLock, - CicInputContext *pCicIC) -{ - return E_NOTIMPL; -} - -/// Selects the IME context. -/// @implemented -HRESULT -CicBridge::SelectEx( - _Inout_ TLS *pTLS, - _Inout_ ITfThreadMgr_P *pThreadMgr, - _In_ HIMC hIMC, - _In_ BOOL fSelect, - _In_ HKL hKL) -{ - CicIMCLock imcLock(hIMC); - if (FAILED(imcLock.m_hr)) - return imcLock.m_hr; - - CicIMCCLock imeContext(imcLock.get().hCtfImeContext); - if (!imeContext) - imeContext.m_hr = E_FAIL; - if (FAILED(imeContext.m_hr)) - return imeContext.m_hr; - - CicInputContext *pCicIC = imeContext.get().m_pCicIC; - if (pCicIC) - pCicIC->m_bSelecting = TRUE; - - if (fSelect) - { - if (pCicIC) - pCicIC->m_dwUnknown6[1] &= ~1; - if (imcLock.get().fOpen) - OnSetOpenStatus(pTLS, pThreadMgr, imcLock, pCicIC); - } - else - { - ITfContext *pContext = GetInputContext(imeContext); - pThreadMgr->RequestPostponedLock(pContext); - if (pCicIC) - pCicIC->m_bSelecting = FALSE; - if (pContext) - pContext->Release(); - } - - return imeContext.m_hr; -} - -/// Used in CicBridge::EnumCreateInputContextCallback and -/// CicBridge::EnumDestroyInputContextCallback. -typedef struct ENUM_CREATE_DESTROY_IC -{ - TLS *m_pTLS; - CicBridge *m_pBridge; -} ENUM_CREATE_DESTROY_IC, *PENUM_CREATE_DESTROY_IC; - -/// Creates input context for the current thread. -/// @implemented -BOOL CALLBACK CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam) -{ - PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; - pData->m_pBridge->CreateInputContext(pData->m_pTLS, hIMC); - return TRUE; -} - -/// Destroys input context for the current thread. -/// @implemented -BOOL CALLBACK CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam) -{ - PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; - pData->m_pBridge->DestroyInputContext(pData->m_pTLS, hIMC); - return TRUE; -} - -/// @implemented -HRESULT -CicBridge::ActivateIMMX( - _Inout_ TLS *pTLS, - _Inout_ ITfThreadMgr_P *pThreadMgr) -{ - HRESULT hr = pThreadMgr->ActivateEx(&m_cliendId, 1); - if (hr != S_OK) - { - m_cliendId = 0; - return E_FAIL; - } - - if (m_cActivateLocks++ != 0) - return S_OK; - - ITfSourceSingle *pSource = NULL; - hr = pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void**)&pSource); - if (FAILED(hr)) - { - DeactivateIMMX(pTLS, pThreadMgr); - return hr; - } - - CFunctionProvider *pProvider = new(cicNoThrow) CFunctionProvider(m_cliendId); - if (!pProvider) - { - hr = E_FAIL; - goto Finish; - } - - pSource->AdviseSingleSink(m_cliendId, IID_ITfFunctionProvider, pProvider); - pProvider->Release(); - - if (!m_pDocMgr) - { - hr = pThreadMgr->CreateDocumentMgr(&m_pDocMgr); - if (FAILED(hr)) - { - hr = E_FAIL; - goto Finish; - } - - SetCompartmentDWORD(m_cliendId, m_pDocMgr, GUID_COMPARTMENT_CTFIME_DIMFLAGS, TRUE, FALSE); - } - - pThreadMgr->SetSysHookSink(this); - - hr = S_OK; - if (pTLS->m_bDestroyed) - { - ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; - ImmEnumInputContext(0, CicBridge::EnumCreateInputContextCallback, (LPARAM)&Data); - } - -Finish: - if (FAILED(hr)) - DeactivateIMMX(pTLS, pThreadMgr); - if (pSource) - pSource->Release(); - return hr; -} - -/// @implemented -HRESULT -CicBridge::DeactivateIMMX( - _Inout_ TLS *pTLS, - _Inout_ ITfThreadMgr_P *pThreadMgr) -{ - if (m_bDeactivating) - return TRUE; - - m_bDeactivating = TRUE; - - if (m_cliendId) - { - ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; - ImmEnumInputContext(0, CicBridge::EnumDestroyInputContextCallback, (LPARAM)&Data); - pTLS->m_bDestroyed = TRUE; - - ITfSourceSingle *pSource = NULL; - if (pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) - pSource->UnadviseSingleSink(m_cliendId, IID_ITfFunctionProvider); - - m_cliendId = 0; - - while (m_cActivateLocks > 0) - { - --m_cActivateLocks; - pThreadMgr->Deactivate(); - } - - if (pSource) - pSource->Release(); - } - - if (m_pDocMgr) - { - m_pDocMgr->Release(); - m_pDocMgr = NULL; - } - - pThreadMgr->SetSysHookSink(NULL); - - m_bDeactivating = FALSE; - - return S_OK; -} - -/// @implemented -HRESULT -CicBridge::InitIMMX(_Inout_ TLS *pTLS) -{ - if (m_bImmxInited) - return S_OK; - - HRESULT hr = S_OK; - if (!pTLS->m_pThreadMgr) - { - ITfThreadMgr *pThreadMgr = NULL; - hr = TF_CreateThreadMgr(&pThreadMgr); - if (FAILED(hr)) - return E_FAIL; - - hr = pThreadMgr->QueryInterface(IID_ITfThreadMgr_P, (void **)&pTLS->m_pThreadMgr); - if (pThreadMgr) - pThreadMgr->Release(); - if (FAILED(hr)) - return E_FAIL; - } - - if (!m_pThreadMgrEventSink) - { - m_pThreadMgrEventSink = - new(cicNoThrow) CThreadMgrEventSink(CThreadMgrEventSink::DIMCallback, NULL, NULL); - if (!m_pThreadMgrEventSink) - { - UnInitIMMX(pTLS); - return E_FAIL; - } - } - - m_pThreadMgrEventSink->SetCallbackPV(m_pThreadMgrEventSink); - m_pThreadMgrEventSink->_Advise(pTLS->m_pThreadMgr); - - if (!pTLS->m_pProfile) - { - pTLS->m_pProfile = new(cicNoThrow) CicProfile(); - if (!pTLS->m_pProfile) - return E_OUTOFMEMORY; - - hr = pTLS->m_pProfile->InitProfileInstance(pTLS); - if (FAILED(hr)) - { - UnInitIMMX(pTLS); - return E_FAIL; - } - } - - hr = pTLS->m_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr_P, (void **)&m_pKeystrokeMgr); - if (FAILED(hr)) - { - UnInitIMMX(pTLS); - return E_FAIL; - } - - hr = InitDisplayAttrbuteLib(&m_LibThread); - if (FAILED(hr)) - { - UnInitIMMX(pTLS); - return E_FAIL; - } - - m_bImmxInited = TRUE; - return S_OK; -} - -/// @implemented -BOOL CicBridge::UnInitIMMX(_Inout_ TLS *pTLS) -{ - UninitDisplayAttrbuteLib(&m_LibThread); - TFUninitLib_Thread(&m_LibThread); - - if (m_pKeystrokeMgr) - { - m_pKeystrokeMgr->Release(); - m_pKeystrokeMgr = NULL; - } - - if (pTLS->m_pProfile) - { - pTLS->m_pProfile->Release(); - pTLS->m_pProfile = NULL; - } - - if (m_pThreadMgrEventSink) - { - m_pThreadMgrEventSink->_Unadvise(); - m_pThreadMgrEventSink->Release(); - m_pThreadMgrEventSink = NULL; - } - - if (pTLS->m_pThreadMgr) - { - pTLS->m_pThreadMgr->Release(); - pTLS->m_pThreadMgr = NULL; - } - - m_bImmxInited = FALSE; - return TRUE; -} - -/// @implemented -STDMETHODIMP CicBridge::OnPreFocusDIM(HWND hwnd) -{ - return S_OK; -} - -/// @unimplemented -STDMETHODIMP CicBridge::OnSysKeyboardProc(UINT, LONG) -{ - return E_NOTIMPL; + return hr; } -/// @implemented -STDMETHODIMP CicBridge::OnSysShellProc(INT, UINT, LONG) +HIMC GetActiveContext(VOID) { - return S_OK; + HWND hwndFocus = ::GetFocus(); + if (!hwndFocus) + hwndFocus = ::GetActiveWindow(); + return ::ImmGetContext(hwndFocus); } /// @implemented -void -CicBridge::PostTransMsg( - _In_ HWND hWnd, - _In_ INT cTransMsgs, - _In_ const TRANSMSG *pTransMsgs) +HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread) { - for (INT i = 0; i < cTransMsgs; ++i, ++pTransMsgs) + if (!pLibThread) + return E_FAIL; + + if (pLibThread->m_pDisplayAttrMgr) { - ::PostMessageW(hWnd, pTransMsgs->message, pTransMsgs->wParam, pTransMsgs->lParam); + pLibThread->m_pDisplayAttrMgr->Release(); + pLibThread->m_pDisplayAttrMgr = NULL; } + + return S_OK; } +/// Gets the charset from a language ID. /// @implemented -HRESULT -CicBridge::ConfigureGeneral( - _Inout_ TLS* pTLS, - _In_ ITfThreadMgr *pThreadMgr, - _In_ HKL hKL, - _In_ HWND hWnd) +BYTE GetCharsetFromLangId(_In_ DWORD dwValue) { - CicProfile *pProfile = pTLS->m_pProfile; - if (!pProfile) - return E_OUTOFMEMORY; - - TF_LANGUAGEPROFILE profile; - HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); - if (FAILED(hr)) - return hr; - - ITfFunctionProvider *pProvider = NULL; - hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); - if (FAILED(hr)) - return hr; - - ITfFnConfigure *pFnConfigure = NULL; - hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigure, (IUnknown**)&pFnConfigure); - if (FAILED(hr)) - { - pProvider->Release(); - return hr; - } - - hr = pFnConfigure->Show(hWnd, profile.langid, profile.guidProfile); - - pFnConfigure->Release(); - pProvider->Release(); - return hr; + CHARSETINFO info; + if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE)) + return 0; + return info.ciCharset; } +/// Selects or unselects the input context. /// @implemented HRESULT -CicBridge::ConfigureRegisterWord( - _Inout_ TLS* pTLS, - _In_ ITfThreadMgr *pThreadMgr, - _In_ HKL hKL, - _In_ HWND hWnd, - _Inout_opt_ LPVOID lpData) +InternalSelectEx( + _In_ HIMC hIMC, + _In_ BOOL fSelect, + _In_ LANGID LangID) { - CicProfile *pProfile = pTLS->m_pProfile; - if (!pProfile) - return E_OUTOFMEMORY; - - TF_LANGUAGEPROFILE profile; - HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); - if (FAILED(hr)) - return hr; + CicIMCLock imcLock(hIMC); + if (!imcLock) + imcLock.m_hr = E_FAIL; + if (FAILED(imcLock.m_hr)) + return imcLock.m_hr; - ITfFunctionProvider *pProvider = NULL; - hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); - if (FAILED(hr)) - return hr; + if (PRIMARYLANGID(LangID) == LANG_CHINESE) + { + imcLock.get().cfCandForm[0].dwStyle = 0; + imcLock.get().cfCandForm[0].dwIndex = (DWORD)-1; + } - ITfFnConfigureRegisterWord *pFunction = NULL; - hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigureRegisterWord, (IUnknown**)&pFunction); - if (FAILED(hr)) + if (!fSelect) { - pProvider->Release(); - return hr; + imcLock.get().fdwInit &= ~INIT_GUIDMAP; + return imcLock.m_hr; } - REGISTERWORDW* pRegWord = (REGISTERWORDW*)lpData; - if (pRegWord) + if (!imcLock.ClearCand()) + return imcLock.m_hr; + + // Populate conversion mode + if (!(imcLock.get().fdwInit & INIT_CONVERSION)) { - if (pRegWord->lpWord) + DWORD dwConv = (imcLock.get().fdwConversion & IME_CMODE_SOFTKBD); + if (LangID) { - hr = E_OUTOFMEMORY; - BSTR bstrWord = SysAllocString(pRegWord->lpWord); - if (bstrWord) + if (PRIMARYLANGID(LangID) == LANG_JAPANESE) { - hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, bstrWord); - SysFreeString(bstrWord); + dwConv |= IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; + } + else if (PRIMARYLANGID(LangID) != LANG_KOREAN) + { + dwConv |= IME_CMODE_NATIVE; } } - else - { - hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, NULL); - } + imcLock.get().fdwConversion |= dwConv; + imcLock.get().fdwInit |= INIT_CONVERSION; } - pProvider->Release(); - pFunction->Release(); - return hr; -} + // Populate sentence mode + imcLock.get().fdwSentence |= IME_SMODE_PHRASEPREDICT; -/*********************************************************************** - * CicProfile - */ + // Populate LOGFONT + if (!(imcLock.get().fdwInit & INIT_LOGFONT)) + { + // Get logical font + LOGFONTW lf; + HDC hDC = ::GetDC(imcLock.get().hWnd); + HGDIOBJ hFont = GetCurrentObject(hDC, OBJ_FONT); + ::GetObjectW(hFont, sizeof(LOGFONTW), &lf); + ::ReleaseDC(imcLock.get().hWnd, hDC); -/// @unimplemented -HRESULT -CicProfile::GetActiveLanguageProfile( - _In_ HKL hKL, - _In_ REFGUID rguid, - _Out_ TF_LANGUAGEPROFILE *pProfile) -{ - return E_NOTIMPL; + imcLock.get().lfFont.W = lf; + imcLock.get().fdwInit |= INIT_LOGFONT; + } + imcLock.get().lfFont.W.lfCharSet = GetCharsetFromLangId(LangID); + + imcLock.InitContext(); + + return imcLock.m_hr; } +class TLS; + /*********************************************************************** * ImeInquire (MSCTFIME.@) * @@ -3332,367 +858,6 @@ CtfImeThreadDetach(VOID) return S_OK; } -/*********************************************************************** - * UIComposition - */ -struct UIComposition -{ - void OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd); - void OnImeCompositionUpdate(CicIMCLock& imcLock); - void OnImeEndComposition(); - void OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam); - void OnPaintTheme(WPARAM wParam); - void OnDestroy(); - - static LRESULT CALLBACK CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -}; - -/// @unimplemented -void UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd) -{ - //FIXME -} - -/// @unimplemented -void UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock) -{ - //FIXME -} - -/// @unimplemented -void UIComposition::OnImeEndComposition() -{ - //FIXME -} - -/// @unimplemented -void UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam) -{ - //FIXME -} - -/// @unimplemented -void UIComposition::OnPaintTheme(WPARAM wParam) -{ - //FIXME -} - -/// @unimplemented -void UIComposition::OnDestroy() -{ - //FIXME -} - -/// @unimplemented -LRESULT CALLBACK -UIComposition::CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_CREATE) - return -1; // FIXME - return 0; -} - -/*********************************************************************** - * UI - */ -struct UI -{ - HWND m_hWnd; - UIComposition *m_pComp; - - UI(HWND hWnd); - virtual ~UI(); - - HRESULT _Create(); - void _Destroy(); - - static void OnCreate(HWND hWnd); - static void OnDestroy(HWND hWnd); - void OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam); -}; - -// For GetWindowLongPtr/SetWindowLongPtr -#define UIGWLP_HIMC 0 -#define UIGWLP_UI sizeof(HIMC) -#define UIGWLP_SIZE (UIGWLP_UI + sizeof(UI*)) - -/// @implemented -UI::UI(HWND hWnd) : m_hWnd(hWnd) -{ -} - -/// @implemented -UI::~UI() -{ - delete m_pComp; -} - -/// @unimplemented -HRESULT UI::_Create() -{ - m_pComp = new(cicNoThrow) UIComposition(); - if (!m_pComp) - return E_OUTOFMEMORY; - - SetWindowLongPtrW(m_hWnd, UIGWLP_UI, (LONG_PTR)this); - //FIXME - return S_OK; -} - -/// @implemented -void UI::_Destroy() -{ - m_pComp->OnDestroy(); - SetWindowLongPtrW(m_hWnd, UIGWLP_UI, 0); -} - -/// @implemented -void UI::OnCreate(HWND hWnd) -{ - UI *pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); - if (pUI) - return; - pUI = new(cicNoThrow) UI(hWnd); - if (pUI) - pUI->_Create(); -} - -/// @implemented -void UI::OnDestroy(HWND hWnd) -{ - UI *pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); - if (!pUI) - return; - - pUI->_Destroy(); - delete pUI; -} - -/// @implemented -void UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam) -{ - m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam); -} - -/*********************************************************************** - * CIMEUIWindowHandler - */ - -struct CIMEUIWindowHandler -{ - static LRESULT CALLBACK ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -}; - -/// @unimplemented -LRESULT CALLBACK -CIMEUIWindowHandler::ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - return 0; //FIXME -} - -/// @unimplemented -LRESULT CALLBACK -CIMEUIWindowHandler::ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - return 0; //FIXME -} - -/// @unimplemented -LRESULT CALLBACK -CIMEUIWindowHandler::ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - return 0; //FIXME -} - -/// @implemented -LRESULT CALLBACK -CIMEUIWindowHandler::ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_MSIME_MOUSE) - return ImeUIMsImeMouseHandler(hWnd, wParam, lParam); - if (uMsg == WM_MSIME_MODEBIAS) - return ImeUIMsImeModeBiasHandler(hWnd, wParam, lParam); - if (uMsg == WM_MSIME_RECONVERTREQUEST) - return ImeUIMsImeReconvertRequest(hWnd, wParam, lParam); - if (uMsg == WM_MSIME_SERVICE) - { - TLS *pTLS = TLS::GetTLS(); - if (pTLS && pTLS->m_pProfile) - { - LANGID LangID; - pTLS->m_pProfile->GetLangId(&LangID); - if (PRIMARYLANGID(LangID) == LANG_KOREAN) - return FALSE; - } - return TRUE; - } - return 0; -} - -/// @unimplemented -LRESULT CALLBACK -CIMEUIWindowHandler::ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TLS *pTLS = TLS::GetTLS(); - if (pTLS && (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) - { - if (uMsg == WM_CREATE) - return -1; - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } - - switch (uMsg) - { - case WM_CREATE: - { - UI::OnCreate(hWnd); - break; - } - case WM_DESTROY: - case WM_ENDSESSION: - { - UI::OnDestroy(hWnd); - break; - } - case WM_IME_STARTCOMPOSITION: - case WM_IME_COMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_SETCONTEXT: - case WM_IME_NOTIFY: - case WM_IME_SELECT: - case WM_TIMER: - { - HIMC hIMC = (HIMC)GetWindowLongPtrW(hWnd, UIGWLP_HIMC); - UI* pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); - CicIMCLock imcLock(hIMC); - switch (uMsg) - { - case WM_IME_STARTCOMPOSITION: - { - pUI->m_pComp->OnImeStartComposition(imcLock, pUI->m_hWnd); - break; - } - case WM_IME_COMPOSITION: - { - if (lParam & GCS_COMPSTR) - { - pUI->m_pComp->OnImeCompositionUpdate(imcLock); - ::SetTimer(hWnd, 0, 10, NULL); - //FIXME - } - break; - } - case WM_IME_ENDCOMPOSITION: - { - ::KillTimer(hWnd, 0); - pUI->m_pComp->OnImeEndComposition(); - break; - } - case WM_IME_SETCONTEXT: - { - pUI->OnImeSetContext(imcLock, wParam, lParam); - ::KillTimer(hWnd, 1); - ::SetTimer(hWnd, 1, 300, NULL); - break; - } - case WM_TIMER: - { - //FIXME - ::KillTimer(hWnd, wParam); - break; - } - case WM_IME_NOTIFY: - case WM_IME_SELECT: - default: - { - pUI->m_pComp->OnPaintTheme(wParam); - break; - } - } - break; - } - default: - { - if (IsMsImeMessage(uMsg)) - return CIMEUIWindowHandler::ImeUIMsImeHandler(hWnd, uMsg, wParam, lParam); - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } - } - - return 0; -} - -/// @implemented -EXTERN_C LRESULT CALLBACK -UIWndProc( - _In_ HWND hWnd, - _In_ UINT uMsg, - _In_ WPARAM wParam, - _In_ LPARAM lParam) -{ - return CIMEUIWindowHandler::ImeUIWndProcWorker(hWnd, uMsg, wParam, lParam); -} - -/// @unimplemented -BOOL RegisterImeClass(VOID) -{ - WNDCLASSEXW wcx; - - if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx)) - { - ZeroMemory(&wcx, sizeof(wcx)); - wcx.cbSize = sizeof(WNDCLASSEXW); - wcx.cbWndExtra = UIGWLP_SIZE; - wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW); - wcx.hInstance = g_hInst; - wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); - wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); - wcx.style = CS_IME | CS_GLOBALCLASS; - wcx.lpfnWndProc = UIWndProc; - wcx.lpszClassName = L"MSCTFIME UI"; - if (!RegisterClassExW(&wcx)) - return FALSE; - } - - if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx)) - { - ZeroMemory(&wcx, sizeof(wcx)); - wcx.cbSize = sizeof(WNDCLASSEXW); - wcx.cbWndExtra = sizeof(DWORD); - wcx.hIcon = NULL; - wcx.hInstance = g_hInst; - wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM); - wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); - wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW; - wcx.lpfnWndProc = UIComposition::CompWndProc; - wcx.lpszClassName = L"MSCTFIME Composition"; - if (!RegisterClassExW(&wcx)) - return FALSE; - } - - return TRUE; -} - -/// @implemented -VOID UnregisterImeClass(VOID) -{ - WNDCLASSEXW wcx; - - GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx); - UnregisterClassW(L"MSCTFIME UI", g_hInst); - DestroyIcon(wcx.hIcon); - DestroyIcon(wcx.hIconSm); - - GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx); - UnregisterClassW(L"MSCTFIME Composition", g_hInst); - DestroyIcon(wcx.hIcon); - DestroyIcon(wcx.hIconSm); -} - /// @implemented BOOL AttachIME(VOID) { diff --git a/dll/ime/msctfime/msctfime.h b/dll/ime/msctfime/msctfime.h index 040ecc11c96..f7ada8fbd6e 100644 --- a/dll/ime/msctfime/msctfime.h +++ b/dll/ime/msctfime/msctfime.h @@ -34,6 +34,23 @@ #include +EXTERN_C BOOLEAN WINAPI DllShutdownInProgress(VOID); + +HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread); +HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread); + +DEFINE_GUID(GUID_COMPARTMENT_CTFIME_DIMFLAGS, 0xA94C5FD2, 0xC471, 0x4031, 0x95, 0x46, 0x70, 0x9C, 0x17, 0x30, 0x0C, 0xB9); +DEFINE_GUID(GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0x85A688F7, 0x6DC8, 0x4F17, 0xA8, 0x3A, 0xB1, 0x1C, 0x09, 0xCD, 0xD7, 0xBF); + #include "resource.h" +#include "bridge.h" +#include "compartment.h" +#include "functions.h" +#include "inputcontext.h" +#include "profile.h" +#include "sinks.h" +#include "tls.h" +#include "ui.h" + extern HINSTANCE g_hInst; diff --git a/dll/ime/msctfime/profile.cpp b/dll/ime/msctfime/profile.cpp new file mode 100644 index 00000000000..9ec7cd12ff3 --- /dev/null +++ b/dll/ime/msctfime/profile.cpp @@ -0,0 +1,173 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Profile of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @implemented +CicProfile::CicProfile() +{ + m_dwFlags &= 0xFFFFFFF0; + m_cRefs = 1; + m_pIPProfiles = NULL; + m_pActiveLanguageProfileNotifySink = NULL; + m_LangID1 = 0; + m_nCodePage = CP_ACP; + m_LangID2 = 0; + m_dwUnknown1 = 0; +} + +/// @implemented +CicProfile::~CicProfile() +{ + if (m_pIPProfiles) + { + if (m_LangID1) + m_pIPProfiles->ChangeCurrentLanguage(m_LangID1); + + m_pIPProfiles->Release(); + m_pIPProfiles = NULL; + } + + if (m_pActiveLanguageProfileNotifySink) + { + m_pActiveLanguageProfileNotifySink->_Unadvise(); + m_pActiveLanguageProfileNotifySink->Release(); + m_pActiveLanguageProfileNotifySink = NULL; + } +} + +/// @implemented +STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + *ppvObj = NULL; + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CicProfile::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CicProfile::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +INT CALLBACK +CicProfile::ActiveLanguageProfileNotifySinkCallback( + REFGUID rguid1, + REFGUID rguid2, + BOOL fActivated, + LPVOID pUserData) +{ + CicProfile *pThis = (CicProfile *)pUserData; + pThis->m_dwFlags &= ~0xE; + return 0; +} + +/// @implemented +HRESULT CicProfile::GetCodePageA(_Out_ UINT *puCodePage) +{ + if (!puCodePage) + return E_INVALIDARG; + + if (m_dwFlags & 2) + { + *puCodePage = m_nCodePage; + return S_OK; + } + + *puCodePage = 0; + + LANGID LangID; + HRESULT hr = GetLangId(&LangID); + if (FAILED(hr)) + return E_FAIL; + + WCHAR szBuff[12]; + INT cch = ::GetLocaleInfoW(LangID, LOCALE_IDEFAULTANSICODEPAGE, szBuff, _countof(szBuff)); + if (cch) + { + szBuff[cch] = 0; + m_nCodePage = *puCodePage = wcstoul(szBuff, NULL, 10); + m_dwFlags |= 2; + } + + return S_OK; +} + +/// @implemented +HRESULT CicProfile::GetLangId(_Out_ LANGID *pLangID) +{ + *pLangID = 0; + + if (!m_pIPProfiles) + return E_FAIL; + + if (m_dwFlags & 4) + { + *pLangID = m_LangID2; + return S_OK; + } + + HRESULT hr = m_pIPProfiles->GetCurrentLanguage(pLangID); + if (SUCCEEDED(hr)) + { + m_dwFlags |= 4; + m_LangID2 = *pLangID; + } + + return hr; +} + +/// @implemented +HRESULT +CicProfile::InitProfileInstance(_Inout_ TLS *pTLS) +{ + HRESULT hr = TF_CreateInputProcessorProfiles(&m_pIPProfiles); + if (FAILED(hr)) + return hr; + + if (!m_pActiveLanguageProfileNotifySink) + { + CActiveLanguageProfileNotifySink *pSink = + new(cicNoThrow) CActiveLanguageProfileNotifySink( + CicProfile::ActiveLanguageProfileNotifySinkCallback, this); + if (!pSink) + { + m_pIPProfiles->Release(); + m_pIPProfiles = NULL; + return E_FAIL; + } + m_pActiveLanguageProfileNotifySink = pSink; + } + + if (pTLS->m_pThreadMgr) + m_pActiveLanguageProfileNotifySink->_Advise(pTLS->m_pThreadMgr); + + return hr; +} + +/// @unimplemented +HRESULT +CicProfile::GetActiveLanguageProfile( + _In_ HKL hKL, + _In_ REFGUID rguid, + _Out_ TF_LANGUAGEPROFILE *pProfile) +{ + return E_NOTIMPL; +} diff --git a/dll/ime/msctfime/profile.h b/dll/ime/msctfime/profile.h new file mode 100644 index 00000000000..2943750ad46 --- /dev/null +++ b/dll/ime/msctfime/profile.h @@ -0,0 +1,51 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Profile of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +#include "sinks.h" + +class CicProfile : public IUnknown +{ +protected: + ITfInputProcessorProfiles *m_pIPProfiles; + CActiveLanguageProfileNotifySink *m_pActiveLanguageProfileNotifySink; + LANGID m_LangID1; + WORD m_padding1; + DWORD m_dwFlags; + UINT m_nCodePage; + LANGID m_LangID2; + WORD m_padding2; + DWORD m_dwUnknown1; + LONG m_cRefs; + + static INT CALLBACK + ActiveLanguageProfileNotifySinkCallback( + REFGUID rguid1, + REFGUID rguid2, + BOOL fActivated, + LPVOID pUserData); + +public: + CicProfile(); + virtual ~CicProfile(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + HRESULT + GetActiveLanguageProfile( + _In_ HKL hKL, + _In_ REFGUID rguid, + _Out_ TF_LANGUAGEPROFILE *pProfile); + HRESULT GetLangId(_Out_ LANGID *pLangID); + HRESULT GetCodePageA(_Out_ UINT *puCodePage); + + HRESULT InitProfileInstance(_Inout_ TLS *pTLS); +}; diff --git a/dll/ime/msctfime/sinks.cpp b/dll/ime/msctfime/sinks.cpp new file mode 100644 index 00000000000..235079c4d94 --- /dev/null +++ b/dll/ime/msctfime/sinks.cpp @@ -0,0 +1,539 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: The sinks of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +/// @implemented +CCompartmentEventSink::CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData) + : m_array() + , m_cRefs(1) + , m_fnEventSink(fnEventSink) + , m_pUserData(pUserData) +{ +} + +/// @implemented +CCompartmentEventSink::~CCompartmentEventSink() +{ +} + +/// @implemented +STDMETHODIMP CCompartmentEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + + *ppvObj = NULL; + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CCompartmentEventSink::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CCompartmentEventSink::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +STDMETHODIMP CCompartmentEventSink::OnChange(REFGUID rguid) +{ + return m_fnEventSink(m_pUserData, rguid); +} + +/// @implemented +HRESULT +CCompartmentEventSink::_Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread) +{ + CESMAP *pCesMap = m_array.Append(1); + if (!pCesMap) + return E_OUTOFMEMORY; + + ITfSource *pSource = NULL; + + HRESULT hr = GetCompartment(pUnknown, rguid, &pCesMap->m_pComp, bThread); + if (FAILED(hr)) + { + hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); + if (FAILED(hr)) + { + hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &pCesMap->m_dwCookie); + if (FAILED(hr)) + { + if (pCesMap->m_pComp) + { + pCesMap->m_pComp->Release(); + pCesMap->m_pComp = NULL; + } + m_array.Remove(m_array.size() - 1, 1); + } + else + { + hr = S_OK; + } + } + } + + if (pSource) + pSource->Release(); + + return hr; +} + +/// @implemented +HRESULT CCompartmentEventSink::_Unadvise() +{ + CESMAP *pCesMap = m_array.data(); + size_t cItems = m_array.size(); + if (!cItems) + return S_OK; + + do + { + ITfSource *pSource = NULL; + HRESULT hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); + if (SUCCEEDED(hr)) + pSource->UnadviseSink(pCesMap->m_dwCookie); + + if (pCesMap->m_pComp) + { + pCesMap->m_pComp->Release(); + pCesMap->m_pComp = NULL; + } + + if (pSource) + pSource->Release(); + + ++pCesMap; + --cItems; + } while (cItems); + + return S_OK; +} + +/***********************************************************************/ + +/// @implemented +CTextEventSink::CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV) +{ + m_cRefs = 1; + m_pUnknown = NULL; + m_dwEditSinkCookie = (DWORD)-1; + m_dwLayoutSinkCookie = (DWORD)-1; + m_fnLayoutChange = NULL; + m_fnEndEdit = fnEndEdit; + m_pCallbackPV = pCallbackPV; +} + +/// @implemented +CTextEventSink::~CTextEventSink() +{ +} + +/// @implemented +STDMETHODIMP CTextEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextEditSink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + if (IsEqualIID(riid, IID_ITfTextLayoutSink)) + { + *ppvObj = static_cast(this); + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CTextEventSink::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CTextEventSink::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +struct TEXT_EVENT_SINK_END_EDIT +{ + TfEditCookie m_ecReadOnly; + ITfEditRecord *m_pEditRecord; + ITfContext *m_pContext; +}; + +/// @implemented +STDMETHODIMP CTextEventSink::OnEndEdit( + ITfContext *pic, + TfEditCookie ecReadOnly, + ITfEditRecord *pEditRecord) +{ + TEXT_EVENT_SINK_END_EDIT Data = { ecReadOnly, pEditRecord, pic }; + return m_fnEndEdit(1, m_pCallbackPV, (LPVOID)&Data); +} + +/// @implemented +STDMETHODIMP CTextEventSink::OnLayoutChange( + ITfContext *pContext, + TfLayoutCode lcode, + ITfContextView *pContextView) +{ + switch (lcode) + { + case TF_LC_CREATE: + return m_fnLayoutChange(3, m_fnEndEdit, pContextView); + case TF_LC_CHANGE: + return m_fnLayoutChange(2, m_fnEndEdit, pContextView); + case TF_LC_DESTROY: + return m_fnLayoutChange(4, m_fnEndEdit, pContextView); + default: + return E_INVALIDARG; + } +} + +/// @implemented +HRESULT CTextEventSink::_Advise(IUnknown *pUnknown, UINT uFlags) +{ + m_pUnknown = NULL; + m_uFlags = uFlags; + + ITfSource *pSource = NULL; + HRESULT hr = pUnknown->QueryInterface(IID_ITfSource, (void**)&pSource); + if (SUCCEEDED(hr)) + { + ITfTextEditSink *pSink = static_cast(this); + if (uFlags & 1) + hr = pSource->AdviseSink(IID_ITfTextEditSink, pSink, &m_dwEditSinkCookie); + if (SUCCEEDED(hr) && (uFlags & 2)) + hr = pSource->AdviseSink(IID_ITfTextLayoutSink, pSink, &m_dwLayoutSinkCookie); + + if (SUCCEEDED(hr)) + { + m_pUnknown = pUnknown; + pUnknown->AddRef(); + } + else + { + pSource->UnadviseSink(m_dwEditSinkCookie); + } + } + + if (pSource) + pSource->Release(); + + return hr; +} + +/// @implemented +HRESULT CTextEventSink::_Unadvise() +{ + if (!m_pUnknown) + return E_FAIL; + + ITfSource *pSource = NULL; + HRESULT hr = m_pUnknown->QueryInterface(IID_ITfSource, (void**)&pSource); + if (SUCCEEDED(hr)) + { + if (m_uFlags & 1) + hr = pSource->UnadviseSink(m_dwEditSinkCookie); + if (m_uFlags & 2) + hr = pSource->UnadviseSink(m_dwLayoutSinkCookie); + + pSource->Release(); + } + + m_pUnknown->Release(); + m_pUnknown = NULL; + + return E_NOTIMPL; +} + +/***********************************************************************/ + +/// @implemented +CThreadMgrEventSink::CThreadMgrEventSink( + _In_ FN_INITDOCMGR fnInit, + _In_ FN_PUSHPOP fnPushPop, + _Inout_ LPVOID pvCallbackPV) +{ + m_fnInit = fnInit; + m_fnPushPop = fnPushPop; + m_pCallbackPV = pvCallbackPV; + m_cRefs = 1; +} + +/// @implemented +STDMETHODIMP CThreadMgrEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfThreadMgrEventSink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CThreadMgrEventSink::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CThreadMgrEventSink::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +INT CALLBACK +CThreadMgrEventSink::DIMCallback( + UINT nCode, + ITfDocumentMgr *pDocMgr1, + ITfDocumentMgr *pDocMgr2, + LPVOID pUserData) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CThreadMgrEventSink::OnInitDocumentMgr(ITfDocumentMgr *pdim) +{ + if (!m_fnInit) + return S_OK; + return m_fnInit(0, pdim, NULL, m_pCallbackPV); +} + +STDMETHODIMP CThreadMgrEventSink::OnUninitDocumentMgr(ITfDocumentMgr *pdim) +{ + if (!m_fnInit) + return S_OK; + return m_fnInit(1, pdim, NULL, m_pCallbackPV); +} + +STDMETHODIMP +CThreadMgrEventSink::OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) +{ + if (!m_fnInit) + return S_OK; + return m_fnInit(2, pdimFocus, pdimPrevFocus, m_pCallbackPV); +} + +STDMETHODIMP CThreadMgrEventSink::OnPushContext(ITfContext *pic) +{ + if (!m_fnPushPop) + return S_OK; + return m_fnPushPop(3, pic, m_pCallbackPV); +} + +STDMETHODIMP CThreadMgrEventSink::OnPopContext(ITfContext *pic) +{ + if (!m_fnPushPop) + return S_OK; + return m_fnPushPop(4, pic, m_pCallbackPV); +} + +void CThreadMgrEventSink::SetCallbackPV(_Inout_ LPVOID pv) +{ + if (!m_pCallbackPV) + m_pCallbackPV = pv; +} + +HRESULT CThreadMgrEventSink::_Advise(ITfThreadMgr *pThreadMgr) +{ + m_pThreadMgr = NULL; + + HRESULT hr = E_FAIL; + ITfSource *pSource = NULL; + if (pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && + pSource->AdviseSink(IID_ITfThreadMgrEventSink, this, &m_dwCookie) == S_OK) + { + m_pThreadMgr = pThreadMgr; + pThreadMgr->AddRef(); + hr = S_OK; + } + + if (pSource) + pSource->Release(); + + return hr; +} + +HRESULT CThreadMgrEventSink::_Unadvise() +{ + HRESULT hr = E_FAIL; + ITfSource *pSource = NULL; + + if (m_pThreadMgr) + { + if (m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && + pSource->UnadviseSink(m_dwCookie) == S_OK) + { + hr = S_OK; + } + + if (pSource) + pSource->Release(); + } + + if (m_pThreadMgr) + { + m_pThreadMgr->Release(); + m_pThreadMgr = NULL; + } + + return hr; +} + +/***********************************************************************/ + +/// @implemented +CActiveLanguageProfileNotifySink::CActiveLanguageProfileNotifySink( + _In_ FN_COMPARE fnCompare, + _Inout_opt_ void *pUserData) +{ + m_dwConnection = (DWORD)-1; + m_fnCompare = fnCompare; + m_cRefs = 1; + m_pUserData = pUserData; +} + +/// @implemented +CActiveLanguageProfileNotifySink::~CActiveLanguageProfileNotifySink() +{ +} + +/// @implemented +STDMETHODIMP CActiveLanguageProfileNotifySink::QueryInterface(REFIID riid, LPVOID* ppvObj) +{ + if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink)) + { + *ppvObj = this; + AddRef(); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +/// @implemented +STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::AddRef() +{ + return ::InterlockedIncrement(&m_cRefs); +} + +/// @implemented +STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::Release() +{ + if (::InterlockedDecrement(&m_cRefs) == 0) + { + delete this; + return 0; + } + return m_cRefs; +} + +/// @implemented +STDMETHODIMP +CActiveLanguageProfileNotifySink::OnActivated( + REFCLSID clsid, + REFGUID guidProfile, + BOOL fActivated) +{ + if (!m_fnCompare) + return 0; + + return m_fnCompare(clsid, guidProfile, fActivated, m_pUserData); +} + +/// @implemented +HRESULT +CActiveLanguageProfileNotifySink::_Advise( + ITfThreadMgr *pThreadMgr) +{ + m_pThreadMgr = NULL; + + ITfSource *pSource = NULL; + HRESULT hr = pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); + if (FAILED(hr)) + return E_FAIL; + + hr = pSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, this, &m_dwConnection); + if (SUCCEEDED(hr)) + { + m_pThreadMgr = pThreadMgr; + pThreadMgr->AddRef(); + hr = S_OK; + } + else + { + hr = E_FAIL; + } + + if (pSource) + pSource->Release(); + + return hr; +} + +/// @implemented +HRESULT +CActiveLanguageProfileNotifySink::_Unadvise() +{ + if (!m_pThreadMgr) + return E_FAIL; + + ITfSource *pSource = NULL; + HRESULT hr = m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); + if (SUCCEEDED(hr)) + { + hr = pSource->UnadviseSink(m_dwConnection); + if (SUCCEEDED(hr)) + hr = S_OK; + } + + if (pSource) + pSource->Release(); + + if (m_pThreadMgr) + { + m_pThreadMgr->Release(); + m_pThreadMgr = NULL; + } + + return hr; +} diff --git a/dll/ime/msctfime/sinks.h b/dll/ime/msctfime/sinks.h new file mode 100644 index 00000000000..9d1fb7885c6 --- /dev/null +++ b/dll/ime/msctfime/sinks.h @@ -0,0 +1,166 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: The sinks of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +/***********************************************************************/ + +typedef struct CESMAP +{ + ITfCompartment *m_pComp; + DWORD m_dwCookie; +} CESMAP, *PCESMAP; + +typedef INT (CALLBACK *FN_EVENTSINK)(LPVOID, REFGUID); + +class CCompartmentEventSink : public ITfCompartmentEventSink +{ + CicArray m_array; + LONG m_cRefs; + FN_EVENTSINK m_fnEventSink; + LPVOID m_pUserData; + +public: + CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData); + virtual ~CCompartmentEventSink(); + + HRESULT _Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread); + HRESULT _Unadvise(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfCompartmentEventSink interface + STDMETHODIMP OnChange(REFGUID rguid) override; +}; + +/***********************************************************************/ + +typedef INT (CALLBACK *FN_ENDEDIT)(INT, LPVOID, LPVOID); +typedef INT (CALLBACK *FN_LAYOUTCHANGE)(UINT nType, FN_ENDEDIT fnEndEdit, ITfContextView *pView); + +class CTextEventSink : public ITfTextEditSink, ITfTextLayoutSink +{ +protected: + LONG m_cRefs; + IUnknown *m_pUnknown; + DWORD m_dwEditSinkCookie; + DWORD m_dwLayoutSinkCookie; + union + { + UINT m_uFlags; + FN_LAYOUTCHANGE m_fnLayoutChange; + }; + FN_ENDEDIT m_fnEndEdit; + LPVOID m_pCallbackPV; + +public: + CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV); + virtual ~CTextEventSink(); + + HRESULT _Advise(IUnknown *pUnknown, UINT uFlags); + HRESULT _Unadvise(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfTextEditSink interface + STDMETHODIMP OnEndEdit( + ITfContext *pic, + TfEditCookie ecReadOnly, + ITfEditRecord *pEditRecord) override; + + // ITfTextLayoutSink interface + STDMETHODIMP + OnLayoutChange( + ITfContext *pContext, + TfLayoutCode lcode, + ITfContextView *pContextView) override; +}; + +/***********************************************************************/ + +typedef INT (CALLBACK *FN_INITDOCMGR)(UINT, ITfDocumentMgr *, ITfDocumentMgr *, LPVOID); +typedef INT (CALLBACK *FN_PUSHPOP)(UINT, ITfContext *, LPVOID); + +class CThreadMgrEventSink : public ITfThreadMgrEventSink +{ +protected: + ITfThreadMgr *m_pThreadMgr; + DWORD m_dwCookie; + FN_INITDOCMGR m_fnInit; + FN_PUSHPOP m_fnPushPop; + DWORD m_dw; + LPVOID m_pCallbackPV; + LONG m_cRefs; + +public: + CThreadMgrEventSink( + _In_ FN_INITDOCMGR fnInit, + _In_ FN_PUSHPOP fnPushPop = NULL, + _Inout_ LPVOID pvCallbackPV = NULL); + virtual ~CThreadMgrEventSink() { } + + void SetCallbackPV(_Inout_ LPVOID pv); + HRESULT _Advise(ITfThreadMgr *pThreadMgr); + HRESULT _Unadvise(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfThreadMgrEventSink interface + STDMETHODIMP OnInitDocumentMgr(ITfDocumentMgr *pdim) override; + STDMETHODIMP OnUninitDocumentMgr(ITfDocumentMgr *pdim) override; + STDMETHODIMP OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) override; + STDMETHODIMP OnPushContext(ITfContext *pic) override; + STDMETHODIMP OnPopContext(ITfContext *pic) override; + + static INT CALLBACK DIMCallback( + UINT nCode, + ITfDocumentMgr *pDocMgr1, + ITfDocumentMgr *pDocMgr2, + LPVOID pUserData); +}; + +/***********************************************************************/ + +class CActiveLanguageProfileNotifySink : public ITfActiveLanguageProfileNotifySink +{ +protected: + typedef INT (CALLBACK *FN_COMPARE)(REFGUID rguid1, REFGUID rguid2, BOOL fActivated, + LPVOID pUserData); + LONG m_cRefs; + ITfThreadMgr *m_pThreadMgr; + DWORD m_dwConnection; + FN_COMPARE m_fnCompare; + LPVOID m_pUserData; + +public: + CActiveLanguageProfileNotifySink(_In_ FN_COMPARE fnCompare, _Inout_opt_ void *pUserData); + virtual ~CActiveLanguageProfileNotifySink(); + + HRESULT _Advise(ITfThreadMgr *pThreadMgr); + HRESULT _Unadvise(); + + // IUnknown interface + STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + + // ITfActiveLanguageProfileNotifySink interface + STDMETHODIMP + OnActivated( + REFCLSID clsid, + REFGUID guidProfile, + BOOL fActivated) override; +}; diff --git a/dll/ime/msctfime/tls.cpp b/dll/ime/msctfime/tls.cpp new file mode 100644 index 00000000000..efb6f9726f5 --- /dev/null +++ b/dll/ime/msctfime/tls.cpp @@ -0,0 +1,56 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Thread-local storage + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +DWORD TLS::s_dwTlsIndex = (DWORD)-1; + +/// @implemented +TLS* TLS::InternalAllocateTLS() +{ + TLS *pTLS = TLS::PeekTLS(); + if (pTLS) + return pTLS; + + if (DllShutdownInProgress()) + return NULL; + + pTLS = (TLS *)cicMemAllocClear(sizeof(TLS)); + if (!pTLS) + return NULL; + + if (!::TlsSetValue(s_dwTlsIndex, pTLS)) + { + cicMemFree(pTLS); + return NULL; + } + + pTLS->m_dwFlags1 |= 1; + pTLS->m_dwUnknown2 |= 1; + return pTLS; +} + +/// @implemented +BOOL TLS::InternalDestroyTLS() +{ + TLS *pTLS = TLS::PeekTLS(); + if (!pTLS) + return FALSE; + + if (pTLS->m_pBridge) + pTLS->m_pBridge->Release(); + if (pTLS->m_pProfile) + pTLS->m_pProfile->Release(); + if (pTLS->m_pThreadMgr) + pTLS->m_pThreadMgr->Release(); + + cicMemFree(pTLS); + ::TlsSetValue(s_dwTlsIndex, NULL); + return TRUE; +} diff --git a/dll/ime/msctfime/tls.h b/dll/ime/msctfime/tls.h new file mode 100644 index 00000000000..28f6d427177 --- /dev/null +++ b/dll/ime/msctfime/tls.h @@ -0,0 +1,74 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Thread-local storage + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +class TLS; + +class CicBridge; +class CicProfile; + +class TLS +{ +public: + static DWORD s_dwTlsIndex; + + DWORD m_dwSystemInfoFlags; + CicBridge *m_pBridge; + CicProfile *m_pProfile; + ITfThreadMgr_P *m_pThreadMgr; + DWORD m_dwFlags1; + DWORD m_dwFlags2; + DWORD m_dwUnknown2; + BOOL m_bDestroyed; + DWORD m_dwNowOpening; + DWORD m_NonEAComposition; + DWORD m_cWnds; + + /** + * @implemented + */ + static BOOL Initialize() + { + s_dwTlsIndex = ::TlsAlloc(); + return s_dwTlsIndex != (DWORD)-1; + } + + /** + * @implemented + */ + static VOID Uninitialize() + { + if (s_dwTlsIndex != (DWORD)-1) + { + ::TlsFree(s_dwTlsIndex); + s_dwTlsIndex = (DWORD)-1; + } + } + + /** + * @implemented + */ + static TLS* GetTLS() + { + if (s_dwTlsIndex == (DWORD)-1) + return NULL; + + return InternalAllocateTLS(); + } + + /** + * @implemented + */ + static TLS* PeekTLS() + { + return (TLS*)::TlsGetValue(TLS::s_dwTlsIndex); + } + + static TLS* InternalAllocateTLS(); + static BOOL InternalDestroyTLS(); +}; diff --git a/dll/ime/msctfime/ui.cpp b/dll/ime/msctfime/ui.cpp new file mode 100644 index 00000000000..74a8c733de0 --- /dev/null +++ b/dll/ime/msctfime/ui.cpp @@ -0,0 +1,393 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: User Interface of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include "msctfime.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctfime); + +UINT WM_MSIME_SERVICE = 0; +UINT WM_MSIME_UIREADY = 0; +UINT WM_MSIME_RECONVERTREQUEST = 0; +UINT WM_MSIME_RECONVERT = 0; +UINT WM_MSIME_DOCUMENTFEED = 0; +UINT WM_MSIME_QUERYPOSITION = 0; +UINT WM_MSIME_MODEBIAS = 0; +UINT WM_MSIME_SHOWIMEPAD = 0; +UINT WM_MSIME_MOUSE = 0; +UINT WM_MSIME_KEYMAP = 0; + +/// @implemented +BOOL IsMsImeMessage(_In_ UINT uMsg) +{ + return (uMsg == WM_MSIME_SERVICE || + uMsg == WM_MSIME_UIREADY || + uMsg == WM_MSIME_RECONVERTREQUEST || + uMsg == WM_MSIME_RECONVERT || + uMsg == WM_MSIME_DOCUMENTFEED || + uMsg == WM_MSIME_QUERYPOSITION || + uMsg == WM_MSIME_MODEBIAS || + uMsg == WM_MSIME_SHOWIMEPAD || + uMsg == WM_MSIME_MOUSE || + uMsg == WM_MSIME_KEYMAP); +} + +/// @implemented +BOOL RegisterMSIMEMessage(VOID) +{ + // Using ANSI (A) version here can reduce binary size. + WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); + WM_MSIME_UIREADY = RegisterWindowMessageA("MSIMEUIReady"); + WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); + WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); + WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); + WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); + WM_MSIME_MODEBIAS = RegisterWindowMessageA("MSIMEModeBias"); + WM_MSIME_SHOWIMEPAD = RegisterWindowMessageA("MSIMEShowImePad"); + WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); + WM_MSIME_KEYMAP = RegisterWindowMessageA("MSIMEKeyMap"); + return (WM_MSIME_SERVICE && + WM_MSIME_UIREADY && + WM_MSIME_RECONVERTREQUEST && + WM_MSIME_RECONVERT && + WM_MSIME_DOCUMENTFEED && + WM_MSIME_QUERYPOSITION && + WM_MSIME_MODEBIAS && + WM_MSIME_SHOWIMEPAD && + WM_MSIME_MOUSE && + WM_MSIME_KEYMAP); +} + +// For GetWindowLongPtr/SetWindowLongPtr +#define UIGWLP_HIMC 0 +#define UIGWLP_UI sizeof(HIMC) +#define UIGWLP_SIZE (UIGWLP_UI + sizeof(UI*)) + +/// @unimplemented +void UIComposition::OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd) +{ + //FIXME +} + +/// @unimplemented +void UIComposition::OnImeCompositionUpdate(CicIMCLock& imcLock) +{ + //FIXME +} + +/// @unimplemented +void UIComposition::OnImeEndComposition() +{ + //FIXME +} + +/// @unimplemented +void UIComposition::OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam) +{ + //FIXME +} + +/// @unimplemented +void UIComposition::OnPaintTheme(WPARAM wParam) +{ + //FIXME +} + +/// @unimplemented +void UIComposition::OnDestroy() +{ + //FIXME +} + +/// @unimplemented +LRESULT CALLBACK +UIComposition::CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CREATE) + return -1; // FIXME + return 0; +} + +/***********************************************************************/ + +/// @implemented +UI::UI(HWND hWnd) : m_hWnd(hWnd) +{ +} + +/// @implemented +UI::~UI() +{ + delete m_pComp; +} + +/// @unimplemented +HRESULT UI::_Create() +{ + m_pComp = new(cicNoThrow) UIComposition(); + if (!m_pComp) + return E_OUTOFMEMORY; + + SetWindowLongPtrW(m_hWnd, UIGWLP_UI, (LONG_PTR)this); + //FIXME + return S_OK; +} + +/// @implemented +void UI::_Destroy() +{ + m_pComp->OnDestroy(); + SetWindowLongPtrW(m_hWnd, UIGWLP_UI, 0); +} + +/// @implemented +void UI::OnCreate(HWND hWnd) +{ + UI *pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); + if (pUI) + return; + pUI = new(cicNoThrow) UI(hWnd); + if (pUI) + pUI->_Create(); +} + +/// @implemented +void UI::OnDestroy(HWND hWnd) +{ + UI *pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); + if (!pUI) + return; + + pUI->_Destroy(); + delete pUI; +} + +/// @implemented +void UI::OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam) +{ + m_pComp->OnImeSetContext(imcLock, m_hWnd, wParam, lParam); +} + +/***********************************************************************/ + +struct CIMEUIWindowHandler +{ + static LRESULT CALLBACK ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +/// @unimplemented +LRESULT CALLBACK +CIMEUIWindowHandler::ImeUIMsImeMouseHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + return 0; //FIXME +} + +/// @unimplemented +LRESULT CALLBACK +CIMEUIWindowHandler::ImeUIMsImeModeBiasHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + return 0; //FIXME +} + +/// @unimplemented +LRESULT CALLBACK +CIMEUIWindowHandler::ImeUIMsImeReconvertRequest(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + return 0; //FIXME +} + +/// @implemented +LRESULT CALLBACK +CIMEUIWindowHandler::ImeUIMsImeHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_MSIME_MOUSE) + return ImeUIMsImeMouseHandler(hWnd, wParam, lParam); + if (uMsg == WM_MSIME_MODEBIAS) + return ImeUIMsImeModeBiasHandler(hWnd, wParam, lParam); + if (uMsg == WM_MSIME_RECONVERTREQUEST) + return ImeUIMsImeReconvertRequest(hWnd, wParam, lParam); + if (uMsg == WM_MSIME_SERVICE) + { + TLS *pTLS = TLS::GetTLS(); + if (pTLS && pTLS->m_pProfile) + { + LANGID LangID; + pTLS->m_pProfile->GetLangId(&LangID); + if (PRIMARYLANGID(LangID) == LANG_KOREAN) + return FALSE; + } + return TRUE; + } + return 0; +} + +/// @unimplemented +LRESULT CALLBACK +CIMEUIWindowHandler::ImeUIWndProcWorker(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + TLS *pTLS = TLS::GetTLS(); + if (pTLS && (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) + { + if (uMsg == WM_CREATE) + return -1; + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + + switch (uMsg) + { + case WM_CREATE: + { + UI::OnCreate(hWnd); + break; + } + case WM_DESTROY: + case WM_ENDSESSION: + { + UI::OnDestroy(hWnd); + break; + } + case WM_IME_STARTCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_SETCONTEXT: + case WM_IME_NOTIFY: + case WM_IME_SELECT: + case WM_TIMER: + { + HIMC hIMC = (HIMC)GetWindowLongPtrW(hWnd, UIGWLP_HIMC); + UI* pUI = (UI*)GetWindowLongPtrW(hWnd, UIGWLP_UI); + CicIMCLock imcLock(hIMC); + switch (uMsg) + { + case WM_IME_STARTCOMPOSITION: + { + pUI->m_pComp->OnImeStartComposition(imcLock, pUI->m_hWnd); + break; + } + case WM_IME_COMPOSITION: + { + if (lParam & GCS_COMPSTR) + { + pUI->m_pComp->OnImeCompositionUpdate(imcLock); + ::SetTimer(hWnd, 0, 10, NULL); + //FIXME + } + break; + } + case WM_IME_ENDCOMPOSITION: + { + ::KillTimer(hWnd, 0); + pUI->m_pComp->OnImeEndComposition(); + break; + } + case WM_IME_SETCONTEXT: + { + pUI->OnImeSetContext(imcLock, wParam, lParam); + ::KillTimer(hWnd, 1); + ::SetTimer(hWnd, 1, 300, NULL); + break; + } + case WM_TIMER: + { + //FIXME + ::KillTimer(hWnd, wParam); + break; + } + case WM_IME_NOTIFY: + case WM_IME_SELECT: + default: + { + pUI->m_pComp->OnPaintTheme(wParam); + break; + } + } + break; + } + default: + { + if (IsMsImeMessage(uMsg)) + return CIMEUIWindowHandler::ImeUIMsImeHandler(hWnd, uMsg, wParam, lParam); + return DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + } + + return 0; +} + +/***********************************************************************/ + +/// @implemented +EXTERN_C LRESULT CALLBACK +UIWndProc( + _In_ HWND hWnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + return CIMEUIWindowHandler::ImeUIWndProcWorker(hWnd, uMsg, wParam, lParam); +} + +/***********************************************************************/ + +/// @unimplemented +BOOL RegisterImeClass(VOID) +{ + WNDCLASSEXW wcx; + + if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx)) + { + ZeroMemory(&wcx, sizeof(wcx)); + wcx.cbSize = sizeof(WNDCLASSEXW); + wcx.cbWndExtra = UIGWLP_SIZE; + wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW); + wcx.hInstance = g_hInst; + wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); + wcx.style = CS_IME | CS_GLOBALCLASS; + wcx.lpfnWndProc = UIWndProc; + wcx.lpszClassName = L"MSCTFIME UI"; + if (!RegisterClassExW(&wcx)) + return FALSE; + } + + if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx)) + { + ZeroMemory(&wcx, sizeof(wcx)); + wcx.cbSize = sizeof(WNDCLASSEXW); + wcx.cbWndExtra = sizeof(DWORD); + wcx.hIcon = NULL; + wcx.hInstance = g_hInst; + wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM); + wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); + wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = UIComposition::CompWndProc; + wcx.lpszClassName = L"MSCTFIME Composition"; + if (!RegisterClassExW(&wcx)) + return FALSE; + } + + return TRUE; +} + +/// @implemented +VOID UnregisterImeClass(VOID) +{ + WNDCLASSEXW wcx; + + GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx); + UnregisterClassW(L"MSCTFIME UI", g_hInst); + DestroyIcon(wcx.hIcon); + DestroyIcon(wcx.hIconSm); + + GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx); + UnregisterClassW(L"MSCTFIME Composition", g_hInst); + DestroyIcon(wcx.hIcon); + DestroyIcon(wcx.hIconSm); +} diff --git a/dll/ime/msctfime/ui.h b/dll/ime/msctfime/ui.h new file mode 100644 index 00000000000..e9433fc734c --- /dev/null +++ b/dll/ime/msctfime/ui.h @@ -0,0 +1,68 @@ +/* + * PROJECT: ReactOS msctfime.ime + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: User Interface of msctfime.ime + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +/***********************************************************************/ + +extern UINT WM_MSIME_SERVICE; +extern UINT WM_MSIME_UIREADY; +extern UINT WM_MSIME_RECONVERTREQUEST; +extern UINT WM_MSIME_RECONVERT; +extern UINT WM_MSIME_DOCUMENTFEED; +extern UINT WM_MSIME_QUERYPOSITION; +extern UINT WM_MSIME_MODEBIAS; +extern UINT WM_MSIME_SHOWIMEPAD; +extern UINT WM_MSIME_MOUSE; +extern UINT WM_MSIME_KEYMAP; + +BOOL IsMsImeMessage(_In_ UINT uMsg); +BOOL RegisterMSIMEMessage(VOID); + +/***********************************************************************/ + +struct UIComposition +{ + void OnImeStartComposition(CicIMCLock& imcLock, HWND hUIWnd); + void OnImeCompositionUpdate(CicIMCLock& imcLock); + void OnImeEndComposition(); + void OnImeSetContext(CicIMCLock& imcLock, HWND hUIWnd, WPARAM wParam, LPARAM lParam); + void OnPaintTheme(WPARAM wParam); + void OnDestroy(); + + static LRESULT CALLBACK CompWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +/***********************************************************************/ + +struct UI +{ + HWND m_hWnd; + UIComposition *m_pComp; + + UI(HWND hWnd); + virtual ~UI(); + + HRESULT _Create(); + void _Destroy(); + + static void OnCreate(HWND hWnd); + static void OnDestroy(HWND hWnd); + void OnImeSetContext(CicIMCLock& imcLock, WPARAM wParam, LPARAM lParam); +}; + +/***********************************************************************/ + +EXTERN_C LRESULT CALLBACK +UIWndProc( + _In_ HWND hWnd, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam); + +BOOL RegisterImeClass(VOID); +VOID UnregisterImeClass(VOID); From b7ad4a2298edc0c232e001c1662205dad022578f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 7 Dec 2023 23:29:28 +0100 Subject: [PATCH 6/6] [SETUPLIB][USETUP] Some cleanup for partition code. - Make the Create*Partition helpers take a size in bytes, not in sectors. This allows them to be easier to use by the caller, alleviating the need for making the size conversion into sectors. Instead it is done internally by the helpers. - Introduce helper macros to easily retrieve the size of a partition entry or a disk in bytes, from their internal representation in number of sectors. - The 'AutoCreate' variable being USETUP-specific, remove it from the PARTENTRY structure and use instead a flag set into the 'New' member. - Rename IsDiskSizeValid to IsPartitionLargeEnough, to better describe what the function is for. --- base/setup/lib/utils/osdetect.c | 6 +- base/setup/lib/utils/partlist.c | 104 +++++++++++++------------ base/setup/lib/utils/partlist.h | 18 +++-- base/setup/usetup/partlist.c | 4 +- base/setup/usetup/usetup.c | 134 ++++++++++++++++---------------- 5 files changed, 139 insertions(+), 127 deletions(-) diff --git a/base/setup/lib/utils/osdetect.c b/base/setup/lib/utils/osdetect.c index 0ee246c60b1..cc45fa907c2 100644 --- a/base/setup/lib/utils/osdetect.c +++ b/base/setup/lib/utils/osdetect.c @@ -806,12 +806,11 @@ CreateNTOSInstallationsList( ASSERT(PartEntry->DiskEntry == DiskEntry); - DPRINT(" Primary Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n", + DPRINT(" Primary Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, FormatState = %lu -- Should I check it? %s\n", PartEntry->PartitionNumber, PartEntry->PartitionIndex, PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE", PartEntry->IsPartitioned ? "TRUE" : "FALSE", PartEntry->New ? "Yes" : "No", - PartEntry->AutoCreate ? "Yes" : "No", PartEntry->FormatState, ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!"); @@ -828,12 +827,11 @@ CreateNTOSInstallationsList( ASSERT(PartEntry->DiskEntry == DiskEntry); - DPRINT(" Logical Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, AutoCreate = %s, FormatState = %lu -- Should I check it? %s\n", + DPRINT(" Logical Partition #%d, index %d - Type 0x%02x, IsLogical = %s, IsPartitioned = %s, IsNew = %s, FormatState = %lu -- Should I check it? %s\n", PartEntry->PartitionNumber, PartEntry->PartitionIndex, PartEntry->PartitionType, PartEntry->LogicalPartition ? "TRUE" : "FALSE", PartEntry->IsPartitioned ? "TRUE" : "FALSE", PartEntry->New ? "Yes" : "No", - PartEntry->AutoCreate ? "Yes" : "No", PartEntry->FormatState, ShouldICheckThisPartition(PartEntry) ? "YES!" : "NO!"); diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c index 49c15e9ffe2..6bb16fed9d4 100644 --- a/base/setup/lib/utils/partlist.c +++ b/base/setup/lib/utils/partlist.c @@ -552,7 +552,7 @@ IsSuperFloppy( } /* The partition lengths should agree */ - PartitionLengthEstimate = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + PartitionLengthEstimate = GetDiskSizeInBytes(DiskEntry); if (PartitionInfo->PartitionLength.QuadPart != PartitionLengthEstimate) { DPRINT1("PartitionLength = %I64u is different from PartitionLengthEstimate = %I64u\n", @@ -676,26 +676,46 @@ CreateInsertBlankRegion( static BOOLEAN InitializePartitionEntry( - IN OUT PPARTENTRY PartEntry, - IN ULONGLONG SectorCount, - IN BOOLEAN AutoCreate) + _Inout_ PPARTENTRY PartEntry, + _In_opt_ ULONGLONG SizeBytes) { PDISKENTRY DiskEntry = PartEntry->DiskEntry; + ULONGLONG SectorCount; + + DPRINT1("Current entry sector count: %I64u\n", PartEntry->SectorCount.QuadPart); - DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart); + /* The entry must not be already partitioned and not be void */ + ASSERT(!PartEntry->IsPartitioned); + ASSERT(PartEntry->SectorCount.QuadPart); + + /* Convert the size in bytes to sector count. SizeBytes being + * zero means the caller wants to use all the empty space. */ + if ((SizeBytes == 0) || (SizeBytes == GetPartEntrySizeInBytes(PartEntry))) + { + /* Use all of the unpartitioned disk space */ + SectorCount = PartEntry->SectorCount.QuadPart; + } + else + { + SectorCount = SizeBytes / DiskEntry->BytesPerSector; + if (SectorCount == 0) + { + /* SizeBytes was certainly less than the minimal size, so fail */ + DPRINT1("Partition size %I64u too small\n", SizeBytes); + return FALSE; + } + } + DPRINT1(" New sector count: %I64u\n", SectorCount); - /* Fail if we try to initialize this partition entry with more sectors than what it actually contains */ + /* Fail if we request more sectors than what the entry actually contains */ if (SectorCount > PartEntry->SectorCount.QuadPart) return FALSE; - /* Fail if the partition is already in use */ - ASSERT(!PartEntry->IsPartitioned); - - if ((AutoCreate != FALSE) || + if ((SectorCount == 0) || (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)) { - PartEntry->AutoCreate = AutoCreate; + /* Reuse the whole current entry */ } else { @@ -703,7 +723,8 @@ InitializePartitionEntry( ULONGLONG SectorCount2; PPARTENTRY NewPartEntry; - /* Create a partition entry that represents the remaining space after the partition to be initialized */ + /* Create a partition entry that represents the remaining space + * after the partition to be initialized */ StartSector = AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment); SectorCount2 = PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - StartSector; @@ -735,7 +756,6 @@ InitializePartitionEntry( PartEntry->FormatState = Unformatted; PartEntry->FileSystem[0] = L'\0'; - // PartEntry->AutoCreate = AutoCreate; PartEntry->BootIndicator = FALSE; DPRINT1("First Sector : %I64u\n", PartEntry->StartSector.QuadPart); @@ -2390,37 +2410,24 @@ GetPrevPartition( return NULL; } -// static -FORCEINLINE +static inline BOOLEAN IsEmptyLayoutEntry( - IN PPARTITION_INFORMATION PartitionInfo) + _In_ PPARTITION_INFORMATION PartitionInfo) { - if (PartitionInfo->StartingOffset.QuadPart == 0 && - PartitionInfo->PartitionLength.QuadPart == 0) - { - return TRUE; - } - - return FALSE; + return (PartitionInfo->StartingOffset.QuadPart == 0 && + PartitionInfo->PartitionLength.QuadPart == 0); } -// static -FORCEINLINE +static inline BOOLEAN IsSamePrimaryLayoutEntry( - IN PPARTITION_INFORMATION PartitionInfo, - IN PDISKENTRY DiskEntry, - IN PPARTENTRY PartEntry) + _In_ PPARTITION_INFORMATION PartitionInfo, + _In_ PPARTENTRY PartEntry) { - if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector && - PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) + return ((PartitionInfo->StartingOffset.QuadPart == GetPartEntryOffsetInBytes(PartEntry)) && + (PartitionInfo->PartitionLength.QuadPart == GetPartEntrySizeInBytes(PartEntry))); // PartitionInfo->PartitionType == PartEntry->PartitionType - { - return TRUE; - } - - return FALSE; } static @@ -2578,12 +2585,12 @@ UpdateDiskLayout( PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0); - if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry)) + if (!IsSamePrimaryLayoutEntry(PartitionInfo, PartEntry)) { DPRINT1("Updating primary partition entry %lu\n", Index); - PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; - PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry); + PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry); PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; PartitionInfo->PartitionType = PartEntry->PartitionType; @@ -2624,8 +2631,8 @@ UpdateDiskLayout( DPRINT1("Updating logical partition entry %lu\n", Index); - PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; - PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry); + PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry); PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; PartitionInfo->PartitionType = PartEntry->PartitionType; @@ -2862,12 +2869,11 @@ BOOLEAN CreatePartition( _In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, - _In_ ULONGLONG SectorCount, - _In_ BOOLEAN AutoCreate) + _In_opt_ ULONGLONG SizeBytes) { ERROR_NUMBER Error; - DPRINT1("CreatePartition(%I64u)\n", SectorCount); + DPRINT1("CreatePartition(%I64u bytes)\n", SizeBytes); if (List == NULL || PartEntry == NULL || PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned) @@ -2883,7 +2889,7 @@ CreatePartition( } /* Initialize the partition entry, inserting a new blank region if needed */ - if (!InitializePartitionEntry(PartEntry, SectorCount, AutoCreate)) + if (!InitializePartitionEntry(PartEntry, SizeBytes)) return FALSE; UpdateDiskLayout(PartEntry->DiskEntry); @@ -2924,11 +2930,11 @@ BOOLEAN CreateExtendedPartition( _In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, - _In_ ULONGLONG SectorCount) + _In_opt_ ULONGLONG SizeBytes) { ERROR_NUMBER Error; - DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount); + DPRINT1("CreateExtendedPartition(%I64u bytes)\n", SizeBytes); if (List == NULL || PartEntry == NULL || PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned) @@ -2944,7 +2950,7 @@ CreateExtendedPartition( } /* Initialize the partition entry, inserting a new blank region if needed */ - if (!InitializePartitionEntry(PartEntry, SectorCount, FALSE)) + if (!InitializePartitionEntry(PartEntry, SizeBytes)) return FALSE; ASSERT(PartEntry->LogicalPartition == FALSE); @@ -3933,7 +3939,7 @@ SetMountedDeviceValues( /* Assign a "\DosDevices\#:" mount point to this partition */ if (PartEntry->DriveLetter) { - StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; + StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry); if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->LayoutBuffer->Signature, StartingOffset)) @@ -3956,7 +3962,7 @@ SetMountedDeviceValues( /* Assign a "\DosDevices\#:" mount point to this partition */ if (PartEntry->DriveLetter) { - StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; + StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry); if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->LayoutBuffer->Signature, StartingOffset)) diff --git a/base/setup/lib/utils/partlist.h b/base/setup/lib/utils/partlist.h index c59b5e1f4b7..d5b20615455 100644 --- a/base/setup/lib/utils/partlist.h +++ b/base/setup/lib/utils/partlist.h @@ -70,9 +70,6 @@ typedef struct _PARTENTRY /* Partition is new, table does not exist on disk yet */ BOOLEAN New; - /* Partition was created automatically */ - BOOLEAN AutoCreate; - /* Partition must be checked */ BOOLEAN NeedsCheck; @@ -227,6 +224,16 @@ RoundingDivide( IN ULONGLONG Divisor); +#define GetPartEntryOffsetInBytes(PartEntry) \ + ((PartEntry)->StartSector.QuadPart * (PartEntry)->DiskEntry->BytesPerSector) + +#define GetPartEntrySizeInBytes(PartEntry) \ + ((PartEntry)->SectorCount.QuadPart * (PartEntry)->DiskEntry->BytesPerSector) + +#define GetDiskSizeInBytes(DiskEntry) \ + ((DiskEntry)->SectorCount.QuadPart * (DiskEntry)->BytesPerSector) + + BOOLEAN IsSuperFloppy( IN PDISKENTRY DiskEntry); @@ -306,14 +313,13 @@ BOOLEAN CreatePartition( _In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, - _In_ ULONGLONG SectorCount, - _In_ BOOLEAN AutoCreate); + _In_opt_ ULONGLONG SizeBytes); BOOLEAN CreateExtendedPartition( _In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, - _In_ ULONGLONG SectorCount); + _In_opt_ ULONGLONG SizeBytes); NTSTATUS DismountVolume( diff --git a/base/setup/usetup/partlist.c b/base/setup/usetup/partlist.c index 5feaf446529..72ae328cbde 100644 --- a/base/setup/usetup/partlist.c +++ b/base/setup/usetup/partlist.c @@ -156,7 +156,7 @@ PartitionDescription( PCSTR Unit; /* Get the partition size */ - PartSize = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector; + PartSize = GetPartEntrySizeInBytes(PartEntry); PrettifySize2(&PartSize, &Unit); if (PartEntry->IsPartitioned == FALSE) @@ -307,7 +307,7 @@ DiskDescription( PCSTR Unit; /* Get the disk size */ - DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + DiskSize = GetDiskSizeInBytes(DiskEntry); PrettifySize1(&DiskSize, &Unit); // diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 61fae743780..59593f38b59 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -79,6 +79,9 @@ static enum { PartTypeExtended // MBR-disk container } PartCreateType = PartTypeData; +/* Flag set in PARTENTRY::New when a partition is created automatically */ +#define PARTITION_NEW_AUTOCREATE 0x80 + /* List of supported file systems for the partition to be formatted */ static PFILE_SYSTEM_LIST FileSystemList = NULL; @@ -1503,18 +1506,18 @@ LayoutSettingsPage(PINPUT_RECORD Ir) } -static BOOL -IsDiskSizeValid(PPARTENTRY PartEntry) +static BOOLEAN +IsPartitionLargeEnough( + _In_ PPARTENTRY PartEntry) { - ULONGLONG size; + /* Retrieve the maximum size in MB (rounded up) */ + ULONGLONG PartSize = RoundingDivide(GetPartEntrySizeInBytes(PartEntry), MB); - size = PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector; - size = (size + (512 * KB)) / MB; /* in MBytes */ - - if (size < USetupData.RequiredPartitionDiskSpace) + if (PartSize < USetupData.RequiredPartitionDiskSpace) { /* Partition is too small so ask for another one */ - DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace); + DPRINT1("Partition is too small (size: %I64u MB), required disk space is %lu MB\n", + PartSize, USetupData.RequiredPartitionDiskSpace); return FALSE; } else @@ -1608,13 +1611,15 @@ SelectPartitionPage(PINPUT_RECORD Ir) ASSERT(CurrentPartition != NULL); ASSERT(!IsContainerPartition(CurrentPartition->PartitionType)); + /* Automatically create the partition on the whole empty space; + * it will be formatted later with default parameters */ CreatePartition(PartitionList, CurrentPartition, - CurrentPartition->SectorCount.QuadPart, - TRUE); + 0ULL); + CurrentPartition->New |= PARTITION_NEW_AUTOCREATE; // FIXME?? Aren't we going to enter an infinite loop, if this test fails?? - if (!IsDiskSizeValid(CurrentPartition)) + if (!IsPartitionLargeEnough(CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, USetupData.RequiredPartitionDiskSpace); @@ -1632,7 +1637,7 @@ SelectPartitionPage(PINPUT_RECORD Ir) DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense... // FIXME?? Aren't we going to enter an infinite loop, if this test fails?? - if (!IsDiskSizeValid(InstallPartition)) + if (!IsPartitionLargeEnough(InstallPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, USetupData.RequiredPartitionDiskSpace); @@ -1737,13 +1742,15 @@ SelectPartitionPage(PINPUT_RECORD Ir) return SELECT_PARTITION_PAGE; } + /* Automatically create the partition on the whole empty space; + * it will be formatted later with default parameters */ CreatePartition(PartitionList, CurrentPartition, - 0ULL, - TRUE); + 0ULL); + CurrentPartition->New |= PARTITION_NEW_AUTOCREATE; } - if (!IsDiskSizeValid(CurrentPartition)) + if (!IsPartitionLargeEnough(CurrentPartition)) { MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY, USetupData.RequiredPartitionDiskSpace); @@ -2040,11 +2047,9 @@ CreatePartitionPage(PINPUT_RECORD Ir) PPARTENTRY PartEntry; PDISKENTRY DiskEntry; ULONG uID; - BOOLEAN Quit; - BOOLEAN Cancel; ULONG MaxSize; - ULONGLONG PartSize; - ULONGLONG SectorCount; + ULONGLONG MaxPartSize, PartSize; + BOOLEAN Quit, Cancel; WCHAR InputBuffer[50]; CHAR LineBuffer[100]; @@ -2078,15 +2083,17 @@ CreatePartitionPage(PINPUT_RECORD Ir) CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION)); + MaxPartSize = GetPartEntrySizeInBytes(PartEntry); + while (TRUE) { - MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB; /* in MBytes (rounded) */ - if (MaxSize > PARTITION_MAXSIZE) - MaxSize = PARTITION_MAXSIZE; + /* Retrieve the maximum size in MB (rounded up) + * and cap it with what the user can enter */ + MaxSize = (ULONG)RoundingDivide(MaxPartSize, MB); + MaxSize = min(MaxSize, PARTITION_MAXSIZE); - ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */ + ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, MaxSize, InputBuffer, &Quit, &Cancel); - if (Quit) { if (ConfirmQuit(Ir)) @@ -2097,50 +2104,41 @@ CreatePartitionPage(PINPUT_RECORD Ir) { return SELECT_PARTITION_PAGE; } - else - { - PartSize = _wcstoui64(InputBuffer, NULL, 10); - /* Retry if too small or too large */ - if (PartSize < 1) - continue; - if (PartSize > MaxSize) - continue; - - /* Convert to bytes */ - if (PartSize == MaxSize) - { - /* Use all of the unpartitioned disk space */ - SectorCount = PartEntry->SectorCount.QuadPart; - } - else - { - /* Calculate the sector count from the size in MB */ - SectorCount = PartSize * MB / DiskEntry->BytesPerSector; + PartSize = _wcstoui64(InputBuffer, NULL, 10); - /* But never get larger than the unpartitioned disk space */ - if (SectorCount > PartEntry->SectorCount.QuadPart) - SectorCount = PartEntry->SectorCount.QuadPart; - } + /* Retry if too small or too large */ + if ((PartSize < 1) || (PartSize > MaxSize)) + continue; - DPRINT("Partition size: %I64u bytes\n", PartSize); + /* + * If the input size, given in MB, specifies the maximum partition + * size, it may slightly under- or over-estimate it due to rounding + * error. In this case, use all of the unpartitioned disk space. + * Otherwise, directly convert the size to bytes. + */ + if (PartSize == MaxSize) + PartSize = MaxPartSize; + else // if (PartSize < MaxSize) + PartSize *= MB; + DPRINT("Partition size: %I64u bytes\n", PartSize); - if (PartCreateType == PartTypeData) - { - CreatePartition(PartitionList, - CurrentPartition, - SectorCount, - FALSE); - } - else // if (PartCreateType == PartTypeExtended) - { - CreateExtendedPartition(PartitionList, - CurrentPartition, - SectorCount); - } + ASSERT(PartSize <= MaxPartSize); - return SELECT_PARTITION_PAGE; + if (PartCreateType == PartTypeData) + { + CreatePartition(PartitionList, + CurrentPartition, + PartSize); } + else // if (PartCreateType == PartTypeExtended) + { + CreateExtendedPartition(PartitionList, + CurrentPartition, + PartSize); + } + + return SELECT_PARTITION_PAGE; } return CREATE_PARTITION_PAGE; @@ -2392,10 +2390,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir) */ if (!SystemPartition->IsPartitioned) { + /* Automatically create the partition; it will be + * formatted later with default parameters */ + // FIXME: Don't use the whole empty space, but a minimal size + // specified from the TXTSETUP.SIF or unattended setup. CreatePartition(PartitionList, SystemPartition, - 0LL, // SystemPartition->SectorCount.QuadPart, - TRUE); + 0ULL); + SystemPartition->New |= PARTITION_NEW_AUTOCREATE; ASSERT(SystemPartition->IsPartitioned); } @@ -2548,9 +2550,9 @@ SelectFileSystemPage(PINPUT_RECORD Ir) MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE); - if (PartEntry->AutoCreate) + if (PartEntry->New & PARTITION_NEW_AUTOCREATE) { - PartEntry->AutoCreate = FALSE; + PartEntry->New &= ~PARTITION_NEW_AUTOCREATE; CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION)); }