//-------------------------------------------------------------------------- // Newfldr.cpp //-------------------------------------------------------------------------- #include "pch.hxx" #include "imagelst.h" #include "newfldr.h" #include #include "conman.h" #include "storutil.h" #include "storecb.h" #include "shlwapip.h" #include "instance.h" #include "demand.h" //-------------------------------------------------------------------------- // Constants //-------------------------------------------------------------------------- #define WM_SETFOLDERSELECT (WM_USER + 1666) //-------------------------------------------------------------------------- // SELECTFOLDER //-------------------------------------------------------------------------- typedef struct tagSELECTFOLDER { DWORD op; FOLDERID idCurrent; // Current Selected Folder FOLDERDIALOGFLAGS dwFlags; // Folder dialog flags LPSTR pszTitle; // Title of the dialog box LPSTR pszText; // Why are you asking for a folder FOLDERID idSelected; // The selected folder CTreeViewFrame *pFrame; // Treeview frame object BOOL fPending; CStoreDlgCB *pCallback; FOLDERID idParent; char szName[CCHMAX_FOLDER_NAME]; } SELECTFOLDER, *LPSELECTFOLDER; //-------------------------------------------------------------------------- // NEWFOLDERDIALOGINIT //-------------------------------------------------------------------------- typedef struct tagNEWFOLDERDIALOGINIT { IN FOLDERID idParent; OUT FOLDERID idNew; BOOL fPending; IN CStoreDlgCB *pCallback; char szName[CCHMAX_FOLDER_NAME]; } NEWFOLDERDIALOGINIT, *LPNEWFOLDERDIALOGINIT; //-------------------------------------------------------------------------- // SelectFolderDlgProc //-------------------------------------------------------------------------- INT_PTR CALLBACK SelectFolderDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK NewFolderDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); HRESULT CreateNewFolder(HWND hwnd, LPCSTR pszName, FOLDERID idParent, LPFOLDERID pidNew, IStoreCallback *pCallback); BOOL EnabledFolder(HWND hwnd, LPSELECTFOLDER pSelect, FOLDERID idFolder); HRESULT GetCreatedFolderId(FOLDERID idParent, LPCSTR pszName, FOLDERID *pid); BOOL SelectFolder_HandleCommand(HWND hwnd, WORD wID, LPSELECTFOLDER pSelect); void SelectFolder_HandleStoreComplete(HWND hwnd, LPSELECTFOLDER pSelect); //-------------------------------------------------------------------------- // Globals //-------------------------------------------------------------------------- static FOLDERID g_idPrevSel = FOLDERID_LOCAL_STORE; //-------------------------------------------------------------------------- // SelectFolderDialog //-------------------------------------------------------------------------- HRESULT SelectFolderDialog( IN HWND hwnd, IN DWORD op, IN FOLDERID idCurrent, IN FOLDERDIALOGFLAGS dwFlags, IN_OPT LPCSTR pszTitle, IN_OPT LPCSTR pszText, OUT_OPT LPFOLDERID pidSelected) { // Locals HRESULT hr=S_OK; UINT uAnswer; SELECTFOLDER Select={0}; // Trace TraceCall("SelectFolderDialog"); // Invalid Args Assert(IsWindow(hwnd)); Assert(((int) op) >= SFD_SELECTFOLDER && op < SFD_LAST); // Initialize Select Folder Select.op = op; if (SFD_MOVEFOLDER == op || (!!(dwFlags & FD_FORCEINITSELFOLDER) && FOLDERID_ROOT != idCurrent)) { Assert(idCurrent != FOLDERID_INVALID); Select.idCurrent = idCurrent; } else { Select.idCurrent = g_idPrevSel; } Select.dwFlags = dwFlags | TREEVIEW_DIALOG; if (g_dwAthenaMode & MODE_OUTLOOKNEWS) Select.dwFlags |= TREEVIEW_NOIMAP | TREEVIEW_NOHTTP; Select.pszTitle = (LPSTR)pszTitle; Select.pszText = (LPSTR)pszText; Select.pCallback = new CStoreDlgCB; if (Select.pCallback == NULL) return(E_OUTOFMEMORY); // Create the Dialog Box if (IDOK != DialogBoxParam(g_hLocRes, ((op == SFD_NEWFOLDER) ? MAKEINTRESOURCE(iddCreateFolder) : MAKEINTRESOURCE(iddSelectFolder)), hwnd, SelectFolderDlgProc, (LPARAM)&Select)) { hr = TraceResult(hrUserCancel); goto exit; } // Return selected folderid g_idPrevSel = Select.idSelected; if (pidSelected) *pidSelected = Select.idSelected; exit: Select.pCallback->Release(); // Done return hr; } //-------------------------------------------------------------------------- // SelectFolderDlgProc //-------------------------------------------------------------------------- INT_PTR CALLBACK SelectFolderDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Locals FOLDERINFO info; HRESULT hr; BOOL fEnable; LPSELECTFOLDER pSelect; HWND hwndT; HWND hwndTree; CHAR sz[256]; WORD wID; RECT rc; FOLDERID id; NEWFOLDERDIALOGINIT NewFolder; FOLDERINFO Folder; CTreeView *pTreeView; // Trace TraceCall("SelectFolderDlgProc"); // Get pSelect pSelect = (LPSELECTFOLDER)GetWndThisPtr(hwnd); switch (msg) { case WM_INITDIALOG: // Better not have it yet Assert(NULL == pSelect); // Set pSelect pSelect = (LPSELECTFOLDER)lParam; // Set This pointer SetWndThisPtr(hwnd, (LPSELECTFOLDER)lParam); if (pSelect->op != SFD_SELECTFOLDER) { Assert(pSelect->pCallback != NULL); pSelect->pCallback->Initialize(hwnd); } if (pSelect->op == SFD_NEWFOLDER) { hwndT = GetDlgItem(hwnd, idcFolderEdit); SetIntlFont(hwndT); SendMessage(hwndT, EM_LIMITTEXT, CCHMAX_FOLDER_NAME - 1, 0); } else if (ISFLAGSET(pSelect->dwFlags, FD_NONEWFOLDERS)) { ShowWindow(GetDlgItem(hwnd, idcNewFolderBtn), SW_HIDE); } // Set the title if (pSelect->pszTitle != NULL) { // Must be a string resourceid if (IS_INTRESOURCE(pSelect->pszTitle)) { // Load the String AthLoadString(PtrToUlong(pSelect->pszTitle), sz, ARRAYSIZE(sz)); // Set Temp SetWindowText(hwnd, sz); } // Otherwise, just use the string else SetWindowText(hwnd, pSelect->pszTitle); } // Do we have some status text if (pSelect->pszText != NULL) { // Must be a resource string id if (IS_INTRESOURCE(pSelect->pszText)) { // Load the String AthLoadString(PtrToUlong(pSelect->pszText), sz, ARRAYSIZE(sz)); // Set Temp SetWindowText(GetDlgItem(hwnd, idcTreeViewText), sz); } // Otherwise, just use the string else SetWindowText(GetDlgItem(hwnd, idcTreeViewText), pSelect->pszText); } // Set the treeview font hwndT = GetDlgItem(hwnd, idcTreeView); Assert(hwndT != NULL); SetIntlFont(hwndT); GetWindowRect(hwndT, &rc); MapWindowPoints(NULL, hwnd, (LPPOINT)&rc, 2); DestroyWindow(hwndT); // Create a Frame pSelect->pFrame = new CTreeViewFrame; if (NULL == pSelect->pFrame) { EndDialog(hwnd, IDCANCEL); return FALSE; } // Initialzie the tree view frame if (FAILED(pSelect->pFrame->Initialize(hwnd, &rc, (TREEVIEW_FLAGS & pSelect->dwFlags)))) { EndDialog(hwnd, IDCANCEL); return FALSE; } // Get the Tree View Object from the Frame pTreeView = pSelect->pFrame->GetTreeView(); // Get the Window Handle if (SUCCEEDED(pTreeView->GetWindow(&hwndTree))) { hwndT = GetDlgItem(hwnd, idcTreeViewText); SetWindowPos(hwndTree, hwndT, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSIZE); } // Refresh the Treeview pTreeView->Refresh(); // Set current selection if (FAILED(pTreeView->SetSelection(pSelect->idCurrent, 0))) { pSelect->idCurrent = g_idPrevSel; pTreeView->SetSelection(pSelect->idCurrent, 0); } // Center Myself CenterDialog(hwnd); // Done return(TRUE); case WM_SETFOLDERSELECT: // Validate Params Assert(wParam != NULL && pSelect != NULL); // Get the Tree View Object pTreeView = pSelect->pFrame->GetTreeView(); // Validate Assert(pTreeView != NULL); // Set current selection pTreeView->SetSelection((FOLDERID)wParam, 0); // Done return(TRUE); case WM_STORE_COMPLETE: SelectFolder_HandleStoreComplete(hwnd, pSelect); return(TRUE); case WM_COMMAND: // Get the Command Id wID = LOWORD(wParam); return(SelectFolder_HandleCommand(hwnd, wID, pSelect)); case TVM_SELCHANGED: // Possibly disable choosing the newly selected folder based on flags we were given fEnable = EnabledFolder(hwnd, pSelect, (FOLDERID)lParam); // Enable the OK Button EnableWindow(GetDlgItem(hwnd, IDOK), fEnable); // Get the new folder button hwnd hwndT = GetDlgItem(hwnd, SFD_SELECTFOLDER == pSelect->op ? idcNewFolderBtn : IDOK); if (hwndT != NULL) { // Get Folder Info if (SUCCEEDED(g_pStore->GetFolderInfo((FOLDERID)lParam, &Folder))) { // fEnable fEnable = Folder.idFolder != FOLDERID_ROOT && Folder.tyFolder != FOLDER_NEWS && !ISFLAGSET(Folder.dwFlags, FOLDER_NOCHILDCREATE); // Enable/disable the window EnableWindow(hwndT, fEnable); // Free g_pStore->FreeRecord(&Folder); } } // Done return(TRUE); case TVM_DBLCLICK: // If Not Creating a Folder: if (pSelect->op != SFD_NEWFOLDER) { // If the OK button isn't enabled, I can't select this folder if (FALSE == IsWindowEnabled(GetDlgItem(hwnd, IDOK))) return(TRUE); pTreeView = pSelect->pFrame->GetTreeView(); id = pTreeView->GetSelection(); hr = g_pStore->GetFolderInfo(id, &info); if (SUCCEEDED(hr)) { if (!FHasChildren(&info, TRUE)) SelectFolder_HandleCommand(hwnd, IDOK, pSelect); g_pStore->FreeRecord(&info); } } // Done return(TRUE); case WM_DESTROY: // Close the Tree View if (pSelect != NULL && pSelect->pFrame != NULL) { // Close the TreeView pSelect->pFrame->CloseTreeView(); // Release the Frame SideAssert(pSelect->pFrame->Release() == 0); } // Done return(TRUE); } // Done return(FALSE); } //-------------------------------------------------------------------------- // SelectFolderDlgProc //-------------------------------------------------------------------------- INT_PTR CALLBACK NewFolderDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Locals HRESULT hr; LPNEWFOLDERDIALOGINIT pNew; WORD wID; FOLDERID id; HWND hwndEdit; // Trace TraceCall("NewFolderDlgProc"); // Get This pNew = (LPNEWFOLDERDIALOGINIT)GetWndThisPtr(hwnd); // Handle the Message switch (msg) { case WM_INITDIALOG: // Shouldn't Have This Assert(pNew == NULL); // Set pNew pNew = (LPNEWFOLDERDIALOGINIT)lParam; // Set this Pointer SetWndThisPtr(hwnd, (LPNEWFOLDERDIALOGINIT)lParam); Assert(pNew->pCallback != NULL); pNew->pCallback->Initialize(hwnd); // Get the Folder Name Edit hwndEdit = GetDlgItem(hwnd, idtxtFolderName); // Correct for intl. SetIntlFont(hwndEdit); // Limit the text SendMessage(hwndEdit, EM_LIMITTEXT, CCHMAX_FOLDER_NAME - 1, 0); // Center CenterDialog(hwnd); // Done return(TRUE); case WM_STORE_COMPLETE: Assert(pNew->fPending); pNew->fPending = FALSE; hr = pNew->pCallback->GetResult(); if (hr == S_FALSE) { EndDialog(hwnd, IDCANCEL); } else if (SUCCEEDED(hr)) { hr = GetCreatedFolderId(pNew->idParent, pNew->szName, &id); if (SUCCEEDED(hr)) pNew->idNew = id; else pNew->idNew = pNew->idParent; EndDialog(hwnd, IDOK); } else { // No need to put up error dialog, CStoreDlgCB already did this on failed OnComplete hwndEdit = GetDlgItem(hwnd, idtxtFolderName); SendMessage(hwndEdit, EM_SETSEL, 0, -1); SetFocus(hwndEdit); } return(TRUE); case WM_COMMAND: // Get the Command Id wID = LOWORD(wParam); // Handle the Command switch (wID) { case IDOK: if (pNew->fPending) return(TRUE); Assert(pNew->pCallback != NULL); pNew->pCallback->Reset(); hwndEdit = GetDlgItem(hwnd, idtxtFolderName); GetWindowText(hwndEdit, pNew->szName, ARRAYSIZE(pNew->szName)); // Try to Create the Folder hr = CreateNewFolder(hwnd, pNew->szName, pNew->idParent, &pNew->idNew, (IStoreCallback *)pNew->pCallback); if (hr == E_PENDING) { pNew->fPending = TRUE; break; } else if (FAILED(hr)) { AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrCreateNewFld), hr); SendMessage(hwndEdit, EM_SETSEL, 0, -1); SetFocus(hwndEdit); break; } // End the dialog EndDialog(hwnd, IDOK); // done return(TRUE); case IDCANCEL: if (pNew->fPending) pNew->pCallback->Cancel(); else // End the dialog EndDialog(hwnd, IDCANCEL); // Done return(TRUE); } // Done break; } // Done return(FALSE); } //-------------------------------------------------------------------------- // CreateNewFolder //-------------------------------------------------------------------------- HRESULT CreateNewFolder(HWND hwnd, LPCSTR pszName, FOLDERID idParent, LPFOLDERID pidNew, IStoreCallback *pCallback) { // Locals HRESULT hr; ULONG cchFolder; FOLDERINFO Folder; // Trace TraceCall("CreateNewFolder"); Assert(pCallback != NULL); // Get Text Length cchFolder = lstrlen(pszName); // Invalid if (0 == cchFolder) return(STORE_E_BADFOLDERNAME); // Filup the Folder Info ZeroMemory(&Folder, sizeof(FOLDERINFO)); Folder.idParent = idParent; Folder.tySpecial = FOLDER_NOTSPECIAL; Folder.pszName = (LPSTR)pszName; Folder.dwFlags = FOLDER_SUBSCRIBED; // Create the Folder hr = g_pStore->CreateFolder(NOFLAGS, &Folder, pCallback); if (hr == E_PENDING) return(hr); // Return the Folder Id if (pidNew) *pidNew = Folder.idFolder; // Done return (hr); } //-------------------------------------------------------------------------- // EnabledFolder //-------------------------------------------------------------------------- BOOL EnabledFolder(HWND hwnd, LPSELECTFOLDER pSelect, FOLDERID idFolder) { // Locals BOOL fRet = FALSE; FOLDERINFO Folder; // Trace TraceCall("EnabledFolder"); // Get Folder Info if (FAILED(g_pStore->GetFolderInfo(idFolder, &Folder))) goto exit; // FD_DISABLEROOT if (ISFLAGSET(pSelect->dwFlags, FD_DISABLEROOT) && FOLDERID_ROOT == idFolder) goto exit; // FD_DISABLEINBOX if (ISFLAGSET(pSelect->dwFlags, FD_DISABLEINBOX) && FOLDER_INBOX == Folder.tySpecial) goto exit; // FD_DISABLEOUTBOX if (ISFLAGSET(pSelect->dwFlags, FD_DISABLEOUTBOX) && FOLDER_OUTBOX == Folder.tySpecial) goto exit; // FD_DISABLESENTITEMS if (ISFLAGSET(pSelect->dwFlags, FD_DISABLESENTITEMS) && FOLDER_SENT == Folder.tySpecial) goto exit; // FD_DISABLESERVERS if (ISFLAGSET(pSelect->dwFlags, FD_DISABLESERVERS) && ISFLAGSET(Folder.dwFlags, FOLDER_SERVER)) goto exit; fRet = TRUE; exit: // Cleanup g_pStore->FreeRecord(&Folder); // Default return fRet; } HRESULT GetCreatedFolderId(FOLDERID idParent, LPCSTR pszName, FOLDERID *pid) { HRESULT hr; HLOCK hLock; FOLDERINFO Folder = {0}; Assert(pszName != NULL); Assert(pid != NULL); hr = g_pStore->Lock(&hLock); if (FAILED(hr)) return(hr); Folder.idParent = idParent; Folder.pszName = (LPSTR)pszName; if (DB_S_FOUND == g_pStore->FindRecord(IINDEX_ALL, COLUMNS_ALL, &Folder, NULL)) { *pid = Folder.idFolder; g_pStore->FreeRecord(&Folder); } else { hr = E_FAIL; } g_pStore->Unlock(&hLock); return(hr); } BOOL SelectFolder_HandleCommand(HWND hwnd, WORD wID, LPSELECTFOLDER pSelect) { HRESULT hr; HWND hwndT; FOLDERID id=FOLDERID_INVALID; NEWFOLDERDIALOGINIT NewFolder; CTreeView *pTreeView; switch (wID) { case idcNewFolderBtn: pTreeView = pSelect->pFrame->GetTreeView(); ZeroMemory(&NewFolder, sizeof(NEWFOLDERDIALOGINIT)); NewFolder.idParent = pTreeView->GetSelection(); NewFolder.pCallback = new CStoreDlgCB; if (NewFolder.pCallback == NULL) // TODO: an error message might be helpful return(TRUE); // Launch the dialog to create a new folder if (IDOK == DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddNewFolder), hwnd, NewFolderDlgProc, (LPARAM)&NewFolder)) { // Select the new folder PostMessage(hwnd, WM_SETFOLDERSELECT, (WPARAM)NewFolder.idNew, 0); } NewFolder.pCallback->Release(); return(TRUE); case IDOK: if (pSelect->fPending) return(TRUE); pTreeView = pSelect->pFrame->GetTreeView(); pSelect->idSelected = pTreeView->GetSelection(); switch (pSelect->op) { case SFD_SELECTFOLDER: break; case SFD_NEWFOLDER: Assert(pSelect->pCallback != NULL); pSelect->pCallback->Reset(); hwndT = GetDlgItem(hwnd, idcFolderEdit); GetWindowText(hwndT, pSelect->szName, ARRAYSIZE(pSelect->szName)); hr = CreateNewFolder(hwnd, pSelect->szName, pSelect->idSelected, &id, (IStoreCallback *)pSelect->pCallback); if (hr == E_PENDING) { pSelect->fPending = TRUE; pSelect->idParent = pSelect->idSelected; return(TRUE); } else if (STORE_S_ALREADYEXISTS == hr) { AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrCreateExists), 0, MB_OK | MB_ICONEXCLAMATION); SendMessage(hwndT, EM_SETSEL, 0, -1); SetFocus(hwndT); return(TRUE); } else if (FAILED(hr)) { AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrCreateNewFld), hr); SendMessage(hwndT, EM_SETSEL, 0, -1); SetFocus(hwndT); return(TRUE); } pSelect->idSelected = id; break; case SFD_MOVEFOLDER: Assert(pSelect->pCallback != NULL); pSelect->pCallback->Reset(); hr = g_pStore->MoveFolder(pSelect->idCurrent, pSelect->idSelected, 0, (IStoreCallback *)pSelect->pCallback); if (hr == E_PENDING) { pSelect->fPending = TRUE; return(TRUE); } else if (FAILED(hr)) { AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrFolderMove), hr); return(TRUE); } pSelect->idSelected = id; break; default: Assert(FALSE); break; } EndDialog(hwnd, IDOK); return(TRUE); case IDCANCEL: if (pSelect->fPending) pSelect->pCallback->Cancel(); else EndDialog(hwnd, IDCANCEL); return(TRUE); default: break; } return(FALSE); } void SelectFolder_HandleStoreComplete(HWND hwnd, LPSELECTFOLDER pSelect) { HRESULT hr; FOLDERID id; HWND hwndT; Assert(pSelect->op != SFD_SELECTFOLDER); Assert(pSelect->fPending); pSelect->fPending = FALSE; hr = pSelect->pCallback->GetResult(); if (hr == S_FALSE) { EndDialog(hwnd, IDCANCEL); return; } switch (pSelect->op) { case SFD_NEWFOLDER: if (SUCCEEDED(hr)) { hr = GetCreatedFolderId(pSelect->idParent, pSelect->szName, &id); if (SUCCEEDED(hr)) pSelect->idSelected = id; else pSelect->idSelected = pSelect->idParent; EndDialog(hwnd, IDOK); } else { // No need to put up error dialog, CStoreDlgCB already did this on failed OnComplete hwndT = GetDlgItem(hwnd, idcFolderEdit); SendMessage(hwndT, EM_SETSEL, 0, -1); SetFocus(hwndT); } break; case SFD_MOVEFOLDER: if (SUCCEEDED(hr)) { pSelect->idSelected = pSelect->idCurrent; EndDialog(hwnd, IDOK); } else if (FAILED(hr)) { AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrFolderMove), hr); } break; default: Assert(FALSE); break; } }