Index: base/shell/explorer-new/cabinet.c =================================================================== --- base/shell/explorer-new/cabinet.c (revision 0) +++ base/shell/explorer-new/cabinet.c (working copy) @@ -0,0 +1,829 @@ +/* + * ReactOS Explorer + * + * Copyright 2012 Katayama Hirofumi MZ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +static const TCHAR szCabinetWndClass[] = TEXT("CabinetWClass"); +static const TCHAR wszAppTitle[] = TEXT("ReactOS Explorer"); + +const GUID IID_ICabinetWindow = + {0xac1a9fe9, 0x012a, 0xcd92, {0x88, 0x32, 0xb8, 0x12, 0x82, 0x2e, 0x9f, 0xcf}}; + + +typedef struct +{ + const ICabinetWindowVtbl *lpVtbl; + LONG Ref; + HWND hWnd; + HWND hListView; + HWND hStatusBar; + HACCEL hAccel; + HIMAGELIST himl; + HIMAGELIST himlSmall; + List *back_history; + List *forward_history; +} ICabinetWindowImpl; + +static IUnknown * +IUnknown_from_impl(ICabinetWindowImpl *This) +{ + return (IUnknown *)&This->lpVtbl; +} + +static ICabinetWindow * +ICabinetWindow_from_impl(ICabinetWindowImpl *This) +{ + return (ICabinetWindow *)&This->lpVtbl; +} + +static ICabinetWindowImpl * +impl_from_ICabinetWindow(ICabinetWindow *iface) +{ + return (ICabinetWindowImpl *)((ULONG_PTR)iface - + FIELD_OFFSET(ICabinetWindowImpl, lpVtbl)); +} + +static VOID +ICabinetWindowImpl_Free(ICabinetWindowImpl *This) +{ + if (This->hListView != NULL) + { + DestroyWindow(This->hListView); + This->hListView = NULL; + } + if (This->hStatusBar != NULL) + { + DestroyWindow(This->hStatusBar); + This->hStatusBar = NULL; + } + if (This->hAccel != NULL) + { + DestroyAcceleratorTable(This->hAccel); + This->hAccel = NULL; + } + This->back_history = List_DeleteAll(This->back_history); + This->forward_history = List_DeleteAll(This->forward_history); + + HeapFree(hProcessHeap, 0, This); +} + +static ULONG STDMETHODCALLTYPE +ICabinetWindowImpl_Release(IN OUT ICabinetWindow *iface) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + ULONG Ret; + + Ret = InterlockedDecrement(&This->Ref); + if (Ret == 0) + ICabinetWindowImpl_Free(This); + + return Ret; +} + +static ULONG STDMETHODCALLTYPE +ICabinetWindowImpl_AddRef(IN OUT ICabinetWindow *iface) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + return InterlockedIncrement(&This->Ref); +} + +static BOOL +ICabinetWindow_OnNCCreate(IN OUT ICabinetWindowImpl *This) +{ + ICabinetWindowImpl_AddRef(ICabinetWindow_from_impl(This)); + + return TRUE; +} + +static VOID +ICabinetWindow_OnNCDestroy(ICabinetWindowImpl *This) +{ + ICabinetWindowImpl_Release(ICabinetWindow_from_impl(This)); + + PostQuitMessage(0); +} + +static VOID +ICabinetWindow_OnSize(IN OUT ICabinetWindowImpl *This) +{ + RECT rc, rcClient; + + GetClientRect(This->hWnd, &rcClient); + + if (IsWindowVisible(This->hStatusBar)) + { + SendMessage(This->hStatusBar, WM_SIZE, 0, 0); + GetWindowRect(This->hStatusBar, &rc); + + MoveWindow(This->hListView, + rcClient.left, rcClient.top, + rcClient.right - rcClient.left, + (rcClient.bottom - rcClient.top) - (rc.bottom - rc.top), + TRUE); + } + else + { + MoveWindow(This->hListView, + rcClient.left, rcClient.top, + rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top, + TRUE); + } +} + +static VOID +ICabinetWindowImpl_InitListView(IN OUT ICabinetWindowImpl *This) +{ + LV_COLUMN column; + HICON hIcon; + + column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH; + column.fmt = LVCFMT_LEFT; + column.cx = 180; + column.pszText = TEXT("File Name"); + column.iSubItem = 0; + ListView_InsertColumn(This->hListView, 0, &column); + + column.cx = 100; + column.pszText = TEXT("Modified Time"); + column.iSubItem = 1; + ListView_InsertColumn(This->hListView, 1, &column); + + column.cx = 120; + column.pszText = TEXT("Type"); + column.iSubItem = 2; + ListView_InsertColumn(This->hListView, 2, &column); + + column.fmt = LVCFMT_RIGHT; + column.cx = 100; + column.pszText = TEXT("Size"); + column.iSubItem = 3; + ListView_InsertColumn(This->hListView, 3, &column); + + This->himl = ImageList_Create( + GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), + ILC_COLORDDB | ILC_MASK, + 32, + 10); + This->himlSmall = ImageList_Create( + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLORDDB | ILC_MASK, + 32, + 10); + + hIcon = LoadIcon(hExplorerInstance, MAKEINTRESOURCE(IDI_FILE)); + ImageList_AddIcon(This->himl, hIcon); + hIcon = LoadIcon(hExplorerInstance, MAKEINTRESOURCE(IDI_FOLDER)); + ImageList_AddIcon(This->himl, hIcon); + + hIcon = (HICON)LoadImage( + hExplorerInstance, + MAKEINTRESOURCE(IDI_FILE), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + 0); + ImageList_AddIcon(This->himlSmall, hIcon); + hIcon = (HICON)LoadImage( + hExplorerInstance, + MAKEINTRESOURCE(IDI_FOLDER), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + 0); + ImageList_AddIcon(This->himlSmall, hIcon); + + ListView_SetImageList(This->hListView, This->himl, LVSIL_NORMAL); + ListView_SetImageList(This->hListView, This->himlSmall, LVSIL_SMALL); +} + +static VOID +ICabinetWindowImpl_Update(IN OUT ICabinetWindowImpl *This) +{ + TCHAR szDir[MAX_PATH], szPath[MAX_PATH]; + HANDLE hFind; + WIN32_FIND_DATA find; + LV_ITEM item; + INT i; + + ListView_DeleteAllItems(This->hListView); + + GetCurrentDirectory(MAX_PATH, szDir); + SetWindowText(This->hWnd, szDir); + + lstrcpy(szPath, szDir); + lstrcat(szPath, TEXT("\\*")); + hFind = FindFirstFile(szPath, &find); + if (hFind != INVALID_HANDLE_VALUE) + { + i = 0; + do + { + if (!lstrcmp(find.cFileName, TEXT(".")) || + !lstrcmp(find.cFileName, TEXT(".."))) + { + continue; + } + + ZeroMemory(&item, sizeof(item)); + item.mask = LVIF_TEXT | LVIF_IMAGE; + item.iItem = i++; + item.pszText = find.cFileName; + if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + item.iImage = 1; /* folder */ + else + item.iImage = 0; /* file */ + ListView_InsertItem(This->hListView, &item); + } while(FindNextFile(hFind, &find)); + FindClose(hFind); + } +} + +static VOID +ICabinetWindow_OnCommand(IN OUT ICabinetWindowImpl *This, + IN WPARAM wParam, + IN LPARAM lParam) +{ + HICON hIcon; + + switch(LOWORD(wParam)) + { + case IDM_UNDO: + /* FIXME */ + break; + + case IDM_REDO: + /* FIXME */ + break; + + case IDM_CUT: + /* FIXME */ + break; + + case IDM_COPY: + /* FIXME */ + break; + + case IDM_PASTE: + /* FIXME */ + break; + + case IDM_DELETE: + /* FIXME */ + break; + + case IDM_SELECTALL: + { + INT i, nCount; + + nCount = ListView_GetItemCount(This->hListView); + for(i = 0; i < nCount; i++) + ListView_SetItemState(This->hListView, i, + LVIS_SELECTED, LVIS_SELECTED); + break; + } + + case IDM_INVERTSELECTION: + { + INT i, nCount; + + nCount = ListView_GetItemCount(This->hListView); + for(i = 0; i < nCount; i++) + { + UINT state; + state = ListView_GetItemState(This->hListView, i, LVIS_SELECTED); + ListView_SetItemState(This->hListView, i, + ((state & LVIS_SELECTED) ? 0 : LVIS_SELECTED), LVIS_SELECTED); + } + break; + } + + case IDM_STATUSBAR: + if (IsWindowVisible(This->hStatusBar)) + ShowWindow(This->hStatusBar, SW_HIDE); + else + ShowWindow(This->hStatusBar, SW_SHOWNOACTIVATE); + ICabinetWindow_OnSize(This); + break; + + case IDM_LARGEICON: + SetWindowStyle(This->hListView, LVS_TYPEMASK, LVS_ICON); + break; + + case IDM_SMALLICON: + SetWindowStyle(This->hListView, LVS_TYPEMASK, LVS_SMALLICON); + break; + + case IDM_LIST: + SetWindowStyle(This->hListView, LVS_TYPEMASK, LVS_LIST); + break; + + case IDM_DETAILS: + SetWindowStyle(This->hListView, LVS_TYPEMASK, LVS_REPORT); + break; + + case IDM_SORTBYNAME: + /* FIXME */ + break; + + case IDM_SORTBYMODIFIED: + /* FIXME */ + break; + + case IDM_SORTBYTYPE: + /* FIXME */ + break; + + case IDM_SORTBYSIZE: + /* FIXME */ + break; + + case IDM_BACK: + /* FIXME */ + if (This->back_history != NULL) + { + TCHAR szCurDir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, szCurDir); + This->forward_history = List_AddHead(This->forward_history, szCurDir); + SetCurrentDirectory(This->back_history->value); + This->back_history = List_DeleteHead(This->back_history); + ICabinetWindowImpl_Update(This); + } + break; + + case IDM_FORWARD: + /* FIXME */ + if (This->forward_history != NULL) + { + TCHAR szCurDir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, szCurDir); + This->back_history = List_AddHead(This->back_history, szCurDir); + SetCurrentDirectory(This->forward_history->value); + This->forward_history = List_DeleteHead(This->forward_history); + ICabinetWindowImpl_Update(This); + } + break; + + case IDM_UP: + { + TCHAR szCurDir[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, szCurDir); + This->back_history = List_AddHead(This->back_history, szCurDir); + This->forward_history = List_DeleteAll(This->forward_history); + SetCurrentDirectory(TEXT("..")); + ICabinetWindowImpl_Update(This); + break; + } + + case IDM_REFRESH: + ICabinetWindowImpl_Update(This); + break; + + case IDM_ABOUT: + hIcon = (HICON)LoadImage(hExplorerInstance, MAKEINTRESOURCE(IDI_START), IMAGE_ICON, 48, 48, LR_SHARED); + ShellAbout(This->hWnd, wszAppTitle, 0, hIcon); + break; + } +} + +static BOOL +ICabinetWindow_OnCreate(IN OUT ICabinetWindowImpl *This) +{ + This->hListView = CreateWindowEx( + 0, + WC_LISTVIEW, + NULL, + WS_CHILD | WS_VISIBLE | WS_TABSTOP | + LVS_ICON | LVS_AUTOARRANGE | LVS_EDITLABELS, + 0, 0, 0, 0, + This->hWnd, + (HMENU)1, + hExplorerInstance, + NULL); + if (This->hListView != NULL) + { + ICabinetWindowImpl_InitListView(This); + ICabinetWindowImpl_Update(This); + + This->hStatusBar = CreateStatusWindow( + WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP, + NULL, + This->hWnd, + 2); + if (This->hStatusBar != NULL) + { + return TRUE; + } + DestroyWindow(This->hListView); + This->hListView = NULL; + } + + return FALSE; +} + +static HRESULT STDMETHODCALLTYPE +ICabinetWindowImpl_QueryInterface(IN OUT ICabinetWindow *iface, + IN REFIID riid, + OUT LPVOID *ppvObj) +{ + ICabinetWindowImpl *This; + + if (ppvObj == NULL) + return E_POINTER; + + This = impl_from_ICabinetWindow(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + *ppvObj = IUnknown_from_impl(This); + } + else if (IsEqualIID(riid, &IID_ICabinetWindow)) + { + *ppvObj = ICabinetWindow_from_impl(This); + } + else + { + *ppvObj = NULL; + return E_NOINTERFACE; + } + + ICabinetWindowImpl_AddRef(iface); + return S_OK; +} + +static const ICabinetWindowVtbl ICabinetWindowImpl_Vtbl; + +static ICabinetWindowImpl * +ICabinetWindowImpl_Construct(VOID) +{ + ICabinetWindowImpl *This; + + This = HeapAlloc(hProcessHeap, 0, sizeof(*This)); + if (This == NULL) + return NULL; + + ZeroMemory(This, sizeof(*This)); + This->lpVtbl = &ICabinetWindowImpl_Vtbl; + This->Ref = 1; + return This; +} + +static HRESULT STDMETHODCALLTYPE +ICabinetWindowImpl_Open(IN OUT ICabinetWindow *iface) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + HRESULT Ret = S_OK; + HWND hWnd; + DWORD dwExStyle; + + if (This->hWnd != NULL) + { + if (IsWindow(This->hWnd)) + { + if (!IsWindowVisible(This->hWnd)) + { + ShowWindow(This->hWnd, SW_SHOW); + } + } + else + goto TryCreateCabinetWnd; + } + else + { +TryCreateCabinetWnd: + dwExStyle = 0; + hWnd = CreateWindowEx(dwExStyle, + szCabinetWndClass, + NULL, + WS_OVERLAPPEDWINDOW | WS_VISIBLE | + WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + NULL, + NULL, + hExplorerInstance, + This); + if (hWnd == NULL) + Ret = E_FAIL; + } + + return Ret; +} + +static HRESULT STDMETHODCALLTYPE +ICabinetWindowImpl_Close(IN OUT ICabinetWindow *iface) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + if (This->hWnd != NULL) + { + DestroyWindow(This->hWnd); + } + + return S_OK; +} + +static HWND STDMETHODCALLTYPE +ICabinetWindowImpl_GetHWND(IN OUT ICabinetWindow *iface) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + return This->hWnd; +} + +HRESULT STDMETHODCALLTYPE +ICabinetWindowImpl_OpenDir(IN OUT ICabinetWindow *iface, + IN LPCTSTR Dir) +{ + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + SetCurrentDirectory(Dir); + ICabinetWindowImpl_Update(This); + return S_OK; +} + +static const ICabinetWindowVtbl ICabinetWindowImpl_Vtbl = +{ + /* IUnknown */ + ICabinetWindowImpl_QueryInterface, + ICabinetWindowImpl_AddRef, + ICabinetWindowImpl_Release, + /* ICabinetWindow */ + ICabinetWindowImpl_Open, + ICabinetWindowImpl_Close, + ICabinetWindowImpl_GetHWND, + ICabinetWindowImpl_OpenDir, +}; + +static VOID +ICabinetWindow_OpenSelectedItems(ICabinetWindowImpl *This) +{ + TCHAR szCurDir[MAX_PATH], szPath[MAX_PATH]; + INT i = -1; + ICabinetWindow *Cabinet; + + do + { + i = ListView_GetNextItem(This->hListView, i, LVNI_SELECTED); + if (i != -1) + { + ListView_GetItemText(This->hListView, i, 0, szPath, MAX_PATH); + DWORD attrs = GetFileAttributes(szPath); + if (attrs != 0xFFFFFFFF) + { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) + { + GetCurrentDirectory(MAX_PATH, szCurDir); + This->back_history = List_AddHead(This->back_history, szCurDir); + This->forward_history = List_DeleteAll(This->forward_history); + Cabinet = ICabinetWindow_from_impl(This); + ICabinetWindowImpl_OpenDir(Cabinet, szPath); + break; + } + else + { + ShellExecute(NULL, NULL, szPath, NULL, NULL, SW_SHOWNORMAL); + } + } + } + } while(i != -1); +} + +static VOID +ICabinetWindow_OnInitMenuPopup(ICabinetWindowImpl *This, HMENU hMenu) +{ + DWORD style; + + style = GetWindowLong(This->hListView, GWL_STYLE); + if ((style & LVS_TYPEMASK) == LVS_ICON) + { + CheckMenuRadioItem(hMenu, + IDM_LARGEICON, IDM_DETAILS, IDM_LARGEICON, MF_BYCOMMAND); + } + if ((style & LVS_TYPEMASK) == LVS_SMALLICON) + { + CheckMenuRadioItem(hMenu, + IDM_LARGEICON, IDM_DETAILS, IDM_SMALLICON, MF_BYCOMMAND); + } + if ((style & LVS_TYPEMASK) == LVS_LIST) + { + CheckMenuRadioItem(hMenu, + IDM_LARGEICON, IDM_DETAILS, IDM_LIST, MF_BYCOMMAND); + } + if ((style & LVS_TYPEMASK) == LVS_REPORT) + { + CheckMenuRadioItem(hMenu, + IDM_LARGEICON, IDM_DETAILS, IDM_DETAILS, MF_BYCOMMAND); + } + + if (IsWindowVisible(This->hStatusBar)) + CheckMenuItem(hMenu, IDM_STATUSBAR, MF_BYCOMMAND | MF_CHECKED); + else + CheckMenuItem(hMenu, IDM_STATUSBAR, MF_BYCOMMAND | MF_UNCHECKED); + + if (This->back_history != NULL) + EnableMenuItem(hMenu, IDM_BACK, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(hMenu, IDM_BACK, MF_BYCOMMAND | MF_GRAYED); + + if (This->forward_history != NULL) + EnableMenuItem(hMenu, IDM_FORWARD, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(hMenu, IDM_FORWARD, MF_BYCOMMAND | MF_GRAYED); +} + +static LRESULT CALLBACK +CabinetWndProc(IN HWND hwnd, + IN UINT uMsg, + IN WPARAM wParam, + IN LPARAM lParam) +{ + ICabinetWindowImpl *This; + + if (uMsg == WM_NCCREATE) + { + LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam; + This = (ICabinetWindowImpl*)pcs->lpCreateParams; + This->hWnd = hwnd; + SetWindowLongPtr(hwnd, 0, (LONG_PTR)This); + return ICabinetWindow_OnNCCreate(This); + } + else + { + This = (ICabinetWindowImpl*)GetWindowLongPtr(hwnd, 0); + } + + switch(uMsg) + { + case WM_CREATE: + if (!ICabinetWindow_OnCreate(This)) + return -1; + break; + + case WM_ACTIVATE: + SetFocus(This->hListView); + break; + + case WM_NCDESTROY: + ICabinetWindow_OnNCDestroy(This); + break; + + case WM_COMMAND: + ICabinetWindow_OnCommand(This, wParam, lParam); + break; + + case WM_SIZE: + ICabinetWindow_OnSize(This); + break; + + case WM_NOTIFY: + { + NMHDR *pnmh = (NMHDR *)lParam; + if (pnmh->idFrom == 1) + { + switch(pnmh->code) + { + case NM_DBLCLK: + case NM_RETURN: + ICabinetWindow_OpenSelectedItems(This); + break; + + case LVN_KEYDOWN: + { + LV_KEYDOWN *pkd; + pkd = (LV_KEYDOWN *)lParam; + if (pkd->wVKey == VK_APPS) + { + /* FIXME: show context menu */ + } + break; + } + + case NM_RCLICK: + /* FIXME: show context menu */ + break; + } + } + break; + } + + case WM_INITMENUPOPUP: + ICabinetWindow_OnInitMenuPopup(This, (HMENU)wParam); + break; + + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + return 0; +} + +BOOL +RegisterCabinetWindowClass(VOID) +{ + WNDCLASSEX wcx = {0}; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + wcx.lpfnWndProc = CabinetWndProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(ICabinetWindowImpl *); + wcx.hInstance = hExplorerInstance; + wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wcx.lpszMenuName = MAKEINTRESOURCE(IDM_CABINETMENU); + wcx.lpszClassName = szCabinetWndClass; + wcx.hIconSm = NULL; + + return RegisterClassEx(&wcx) != 0; +} + +ICabinetWindow* +CreateCabinetWindow(VOID) +{ + ICabinetWindowImpl *This; + ICabinetWindow *CabinetWindow; + + This = ICabinetWindowImpl_Construct(); + if (This != NULL) + { + CabinetWindow = ICabinetWindow_from_impl(This); + + This->hAccel = LoadAccelerators( + hExplorerInstance, + MAKEINTRESOURCE(IDA_CABINET)); + if (This->hAccel != NULL) + { + ICabinetWindowImpl_Open(CabinetWindow); + + return CabinetWindow; + } + + ICabinetWindowImpl_Free(This); + } + + return NULL; +} + +VOID +CabinetProcessMessages(IN OUT ICabinetWindow *iface) +{ + MSG Msg; + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) + { + if (Msg.message == WM_QUIT) + break; + + if (!TranslateAccelerator(This->hWnd, This->hAccel, &Msg)) + { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } +} + +VOID +CabinetMessageLoop(IN OUT ICabinetWindow *iface) +{ + MSG Msg; + BOOL Ret; + ICabinetWindowImpl *This = impl_from_ICabinetWindow(iface); + + while (1) + { + Ret = (GetMessage(&Msg, NULL, 0, 0) != 0); + + if (Ret != -1) + { + if (!Ret) + break; + + if (!TranslateAccelerator(This->hWnd, This->hAccel, &Msg)) + { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + } + } +} Index: base/shell/explorer-new/CMakeLists.txt =================================================================== --- base/shell/explorer-new/CMakeLists.txt (revision 57831) +++ base/shell/explorer-new/CMakeLists.txt (working copy) @@ -5,6 +5,7 @@ set_rc_compiler() list(APPEND SOURCE + cabinet.c desktop.c dragdrop.c explorer.c Index: base/shell/explorer-new/explorer.c =================================================================== --- base/shell/explorer-new/explorer.c (revision 57831) +++ base/shell/explorer-new/explorer.c (working copy) @@ -347,16 +347,102 @@ return bRet; } +List *List_CreateNode(LPCTSTR value) +{ + List *node = (List *)HeapAlloc(hProcessHeap, 0, sizeof(List)); + node->next = NULL; + node->value = _tcsdup(value); + return node; +} + +VOID List_DeleteNode(List *node) +{ + free(node->value); + HeapFree(hProcessHeap, 0, node); +} + +List *List_DeleteAll(List *head) +{ + List *next; + while(head != NULL) + { + next = head->next; + List_DeleteNode(head); + head = next; + } + return NULL; +} + +List *List_AddHead(List *head, LPTSTR value) +{ + List *node = List_CreateNode(value); + node->next = head; + return node; +} + +List *List_DeleteHead(List *head) +{ + List *next; + + if (head == NULL) + return NULL; + + next = head->next; + List_DeleteNode(head); + return next; +} + +static VOID +DoShellDesktop(VOID) +{ + ITrayWindow *Tray = NULL; + HANDLE hShellDesktop = NULL; + + if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass()) + { + Tray = CreateTrayWindow(); + + if (Tray != NULL) + hShellDesktop = DesktopCreateWindow(Tray); + } + + /* WinXP: Notify msgina to hide the welcome screen */ + if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) + SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); + + if (Tray != NULL) + TrayMessageLoop(Tray); + + if (hShellDesktop != NULL) + DesktopDestroyShellWindow(hShellDesktop); +} + +static VOID +DoCabinet(VOID) +{ + ICabinetWindow *Cabinet = NULL; + + /* FIXME: Parse the command line arguments */ + if (RegisterCabinetWindowClass()) + { + Cabinet = CreateCabinetWindow(); + if (Cabinet != NULL) + { + CabinetMessageLoop(Cabinet); + } + } +} + INT WINAPI _tWinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPTSTR lpCmdLine, IN INT nCmdShow) { - ITrayWindow *Tray = NULL; - HANDLE hShellDesktop = NULL; BOOL CreateShellDesktop = FALSE; + InitCommonControls(); + if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkExplorer) != ERROR_SUCCESS) @@ -387,32 +473,14 @@ if (CreateShellDesktop) { - if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass()) - { - Tray = CreateTrayWindow(); - - if (Tray != NULL) - hShellDesktop = DesktopCreateWindow(Tray); - } - - /* WinXP: Notify msgina to hide the welcome screen */ - if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) - SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); + DoShellDesktop(); } else { - /* A shell is already loaded. Parse the command line arguments - and unless we need to do something specific simply display - the desktop in a separate explorer window */ - /* FIXME */ + /* A shell is already loaded. */ + DoCabinet(); } - if (Tray != NULL) - TrayMessageLoop(Tray); - - if (hShellDesktop != NULL) - DesktopDestroyShellWindow(hShellDesktop); - /* FIXME - shutdown SSO Thread */ OleUninitialize(); Index: base/shell/explorer-new/explorer.rc =================================================================== --- base/shell/explorer-new/explorer.rc (revision 57831) +++ base/shell/explorer-new/explorer.rc (working copy) @@ -10,6 +10,8 @@ IDI_START ICON DISCARDABLE res/start.ico IDB_STARTMENU BITMAP DISCARDABLE res/logov.bmp +IDI_FOLDER ICON DISCARDABLE res/folder.ico +IDI_FILE ICON DISCARDABLE res/file.ico IDB_TASKBARPROP_AUTOHIDE BITMAP DISCARDABLE res/auto_hide.bmp IDB_TASKBARPROP_LOCK_GROUP_NOQL BITMAP DISCARDABLE res/lock_group_noql.bmp @@ -21,6 +23,25 @@ IDB_TASKBARPROP_NOLOCK_NOGROUP_QL BITMAP DISCARDABLE res/nolock_nogroup_ql.bmp IDB_TASKBARPROP_NOLOCK_GROUP_QL BITMAP DISCARDABLE res/nolock_group_ql.bmp +IDA_CABINET ACCELERATORS +BEGIN + "Z", IDM_UNDO, VIRTKEY, CONTROL + "Y", IDM_REDO, VIRTKEY, CONTROL + "X", IDM_CUT, VIRTKEY, CONTROL + "C", IDM_COPY, VIRTKEY, CONTROL + "V", IDM_PASTE, VIRTKEY, CONTROL + VK_DELETE, IDM_CUT, VIRTKEY, SHIFT + VK_INSERT, IDM_COPY, VIRTKEY, CONTROL + VK_INSERT, IDM_PASTE, VIRTKEY, SHIFT + "A", IDM_SELECTALL, VIRTKEY, CONTROL + VK_LEFT, IDM_BACK, VIRTKEY, ALT + VK_RIGHT, IDM_FORWARD, VIRTKEY, ALT + VK_UP, IDM_UP, VIRTKEY, ALT + VK_BACK, IDM_UP, VIRTKEY + VK_F5, IDM_REFRESH, VIRTKEY + VK_DELETE, IDM_DELETE, VIRTKEY +END + // UTF-8 #pragma code_page(65001) #ifdef LANGUAGE_BG_BG Index: base/shell/explorer-new/lang/en-US.rc =================================================================== --- base/shell/explorer-new/lang/en-US.rc (revision 57831) +++ base/shell/explorer-new/lang/en-US.rc (working copy) @@ -62,6 +62,59 @@ END END +IDM_CABINETMENU MENUEX DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM SEPARATOR + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", IDM_UNDO + MENUITEM "&Redo\tCtrl+Z", IDM_REDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", IDM_CUT + MENUITEM "&Copy\tCtrl+C", IDM_COPY + MENUITEM "&Paste\tCtrl+V", IDM_PASTE + MENUITEM "&Delete\tDel", IDM_DELETE + MENUITEM SEPARATOR + MENUITEM "Select &All\tCtrl+A", IDM_SELECTALL + MENUITEM "&Invert Selection", IDM_INVERTSELECTION + END + POPUP "&View" + BEGIN + MENUITEM "Status &Bar", IDM_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "La&rge Icon", IDM_LARGEICON + MENUITEM "Small Ico&n", IDM_SMALLICON + MENUITEM "&List", IDM_LIST + MENUITEM "&Details", IDM_DETAILS + MENUITEM SEPARATOR + POPUP "S&ort" + BEGIN + MENUITEM "By Name", IDM_SORTBYNAME + MENUITEM "By Modified Time", IDM_SORTBYMODIFIED + MENUITEM "By Type", IDM_SORTBYTYPE + MENUITEM "By Size", IDM_SORTBYSIZE + END + MENUITEM SEPARATOR + POPUP "&Go" + BEGIN + MENUITEM "Back\tAlt+Left", IDM_BACK + MENUITEM "Forward\tAlt+Right", IDM_FORWARD + MENUITEM "Up\tAlt+Up", IDM_UP + END + MENUITEM "&Refresh\tF5", IDM_REFRESH + END + POPUP "&Tool" + BEGIN + MENUITEM SEPARATOR + END + POPUP "&Help" + BEGIN + MENUITEM "&About Explorer", IDM_ABOUT + END +END IDD_TASKBARPROP_TASKBAR DIALOGEX 0, 0, 252, 218 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU @@ -122,7 +175,6 @@ CONTROL "", IDC_TASKBARPROP_DESKBANDLIST, "SysTreeView32",WS_BORDER | WS_TABSTOP | WS_DISABLED, 7,20,236,160, WS_EX_CLIENTEDGE END - STRINGTABLE DISCARDABLE BEGIN IDS_START "Start" Index: base/shell/explorer-new/precomp.h =================================================================== --- base/shell/explorer-new/precomp.h (revision 57831) +++ base/shell/explorer-new/precomp.h (working copy) @@ -125,7 +125,6 @@ /* * explorer.c */ - LONG SetWindowStyle(IN HWND hWnd, IN LONG dwStyleMask, @@ -160,6 +159,18 @@ IN LPCTSTR lpSubKey, IN LPCTSTR lpValue); +typedef struct List +{ + struct List *next; + LPTSTR value; +} List; + +List *List_CreateNode(LPCTSTR value); +VOID List_DeleteNode(List *node); +List *List_AddHead(List *head, LPTSTR value); +List *List_DeleteHead(List *head); +List *List_DeleteAll(List *head); + /* * traywnd.c */ @@ -401,4 +412,48 @@ CreateTaskSwitchWnd(IN HWND hWndParent, IN OUT ITrayWindow *Tray); +/* + * cabinet.c + */ +#define INTERFACE ICabinetWindow +DECLARE_INTERFACE_(ICabinetWindow,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** ICabinetWindow ***/ + STDMETHOD_(HRESULT,Open) (THIS) PURE; + STDMETHOD_(HRESULT,Close) (THIS) PURE; + STDMETHOD_(HWND,GetHWND) (THIS) PURE; + STDMETHOD_(HRESULT,OpenDir) (THIS_ LPCTSTR Dir) PURE; +}; +#undef INTERFACE +#if defined(COBJMACROS) +/*** IUnknown methods ***/ +#define ICabinetWindow_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define ICabinetWindow_AddRef(p) (p)->lpVtbl->AddRef(p) +#define ICabinetWindow_Release(p) (p)->lpVtbl->Release(p) +/*** ICabinetWindow methods ***/ +#define ICabinetWindow_Open(p) (p)->lpVtbl->Open(p) +#define ICabinetWindow_Close(p) (p)->lpVtbl->Close(p) +#define ICabinetWindow_GetHWND(p) (p)->lpVtbl->GetHWND(p) +#define ICabinetWindow_OpenDir(p,d) (p)->lpVtbl->OpenDir(p,d) +#endif + +BOOL +RegisterCabinetWindowClass(VOID); + +ICabinetWindow* +CreateCabinetWindow(VOID); + +VOID +CabinetProcessMessages(IN OUT ICabinetWindow *iface); + +VOID +CabinetMessageLoop(IN OUT ICabinetWindow *iface); + +extern List *back_history; +extern List *forward_history; + #endif /* _EXPLORER_PRECOMP__H_ */ Index: base/shell/explorer-new/resource.h =================================================================== --- base/shell/explorer-new/resource.h (revision 57831) +++ base/shell/explorer-new/resource.h (working copy) @@ -3,6 +3,8 @@ #define IDC_STATIC -1 #define IDI_START 101 +#define IDI_FOLDER 102 +#define IDI_FILE 103 #define IDS_START 101 #define IDS_PROPERTIES 102 @@ -14,9 +16,12 @@ #define IDM_TRAYWND 101 #define IDM_STARTMENU 102 +#define IDM_CABINETMENU 103 #define IDB_STARTMENU 101 +#define IDA_CABINET 101 + #define ID_SHELL_CMD_FIRST 0xF #define ID_SHELL_CMD_LAST 0x7FEF #define ID_SHELL_CMD_PROPERTIES (ID_SHELL_CMD_LAST + 1) @@ -53,6 +58,28 @@ #define IDM_UNDOCKCOMPUTER 410 #define IDM_SHUTDOWN 506 #define IDM_LASTSTARTMENU_SEPARATOR 450 +#define IDM_UNDO 521 +#define IDM_REDO 522 +#define IDM_CUT 523 +#define IDM_COPY 524 +#define IDM_PASTE 525 +#define IDM_SELECTALL 526 +#define IDM_STATUSBAR 527 +#define IDM_LARGEICON 528 +#define IDM_SMALLICON 529 +#define IDM_LIST 530 +#define IDM_DETAILS 531 +#define IDM_SORTBYNAME 532 +#define IDM_SORTBYMODIFIED 533 +#define IDM_SORTBYTYPE 534 +#define IDM_SORTBYSIZE 535 +#define IDM_BACK 536 +#define IDM_FORWARD 537 +#define IDM_UP 538 +#define IDM_REFRESH 539 +#define IDM_INVERTSELECTION 540 +#define IDM_DELETE 541 +#define IDM_ABOUT 542 /* Taskbar resources */ #define IDD_TASKBARPAGE 2000