//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//  Copyright (C) Microsoft Corporation, 1995 - 1995.
//
//  File:       shrpage.cxx
//
//  Contents:   "Sharing" shell property page extension
//
//  History:    6-Apr-95        BruceFo     Created
//
//--------------------------------------------------------------------------

#include "headers.hxx"
#pragma hdrstop

#include "resource.h"
#include "helpids.h"
#include "dlgnew.hxx"
#include "acl.hxx"
#include "shrinfo.hxx"
#include "shrpage.hxx"
#include "util.hxx"

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::DlgProcPage, static public
//
//  Synopsis:   Dialog Procedure for all CSharingPropertyPage
//
//--------------------------------------------------------------------------

INT_PTR CALLBACK
CSharingPropertyPage::DlgProcPage(
    IN HWND hwnd,
    IN UINT msg,
    IN WPARAM wParam,
    IN LPARAM lParam
    )
{
    CSharingPropertyPage* pThis = NULL;

    if (msg==WM_INITDIALOG)
    {
        SHARE_PROPSHEETPAGE* sprop = (SHARE_PROPSHEETPAGE*)lParam;
        pThis = new CSharingPropertyPage(hwnd, sprop->pszMachine, sprop->pszShareName);
        if (NULL != pThis)
        {
            if (FAILED(pThis->InitInstance()))
            {
                delete pThis;
                pThis = NULL;
            }
        }

        SetWindowLongPtr(hwnd,GWLP_USERDATA,(LPARAM)pThis);
    }
    else
    {
        pThis = (CSharingPropertyPage*) GetWindowLongPtr(hwnd,GWLP_USERDATA);
    }

    if (pThis != NULL)
    {
        return pThis->_PageProc(hwnd,msg,wParam,lParam);
    }
    else
    {
        return FALSE;
    }
}


//+-------------------------------------------------------------------------
//
//  Member:     CSharingPropertyPage::SizeWndProc, public
//
//  Synopsis:   "allow" edit window subclass proc to disallow non-numeric
//              characters.
//
//  History:    5-Apr-95 BruceFo  Created
//
//--------------------------------------------------------------------------

LRESULT CALLBACK
CSharingPropertyPage::SizeWndProc(
    IN HWND hwnd,
    IN UINT wMsg,
    IN WPARAM wParam,
    IN LPARAM lParam
    )
{
    switch (wMsg)
    {
    case WM_CHAR:
    {
        WCHAR chCharCode = (WCHAR)wParam;
        if (   (chCharCode == TEXT('\t'))
            || (chCharCode == TEXT('\b'))
            || (chCharCode == TEXT('\n'))
//          || (chCharCode == TEXT('\x1b')) // ESCAPE key
            )
        {
            break;
        }

        if (chCharCode < TEXT('0') || chCharCode > TEXT('9'))
        {
            // bad key: ignore it
            MessageBeep(0xffffffff);    // let user know it's an illegal char
            return FALSE;
        }

        break;
    }
    } // end of switch

    CSharingPropertyPage* pThis = (CSharingPropertyPage*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
    appAssert(NULL != pThis);
    appAssert(NULL != pThis->_pfnAllowProc);
    return CallWindowProc(pThis->_pfnAllowProc, hwnd, wMsg, wParam, lParam);
}


//+--------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::CSharingPropertyPage, public
//
//  Synopsis:   Constructor
//
//---------------------------------------------------------------------------

CSharingPropertyPage::CSharingPropertyPage(
    IN HWND hwndPage,
    IN PWSTR pszMachine,
    IN PWSTR pszShare
    )
    :
    _hwndPage(hwndPage),
    _pszMachine(pszMachine),
    _pszShare(pszShare),
    _bDirty(FALSE),
    _bShareNameChanged(FALSE),
    _bPathChanged(FALSE),
    _bCommentChanged(FALSE),
    _bUserLimitChanged(FALSE),
    _bSecDescChanged(FALSE),
    _wMaxUsers(DEFAULT_MAX_USERS),
    _pCurInfo(NULL),
    _pszReplacePath(NULL),
    _pfnAllowProc(NULL)
{
    INIT_SIG(CSharingPropertyPage);
    appAssert(NULL != _pszShare);
}


//+--------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::~CSharingPropertyPage, public
//
//  Synopsis:   Destructor
//
//---------------------------------------------------------------------------

CSharingPropertyPage::~CSharingPropertyPage()
{
    CHECK_SIG(CSharingPropertyPage);

    delete _pCurInfo;
    _pCurInfo = NULL;

    delete[] _pszReplacePath;
    _pszReplacePath = NULL;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::InitInstance, public
//
//  Synopsis:   Part II of the constuctor process
//
//  Notes:      We don't want to handle any errors in constuctor, so this
//              method is necessary for the second phase error detection.
//
//--------------------------------------------------------------------------

HRESULT
CSharingPropertyPage::InitInstance(
    VOID
    )
{
    CHECK_SIG(CSharingPropertyPage);
    appDebugOut((DEB_ITRACE, "CSharingPropertyPage::InitInstance\n"));

    SHARE_INFO_502* info502;
    NET_API_STATUS ret = NetShareGetInfo(_pszMachine, _pszShare, 502, (LPBYTE*)&info502);
    if (ret == NERR_Success)
    {
        _pCurInfo = new CShareInfo(info502);
        if (NULL == _pCurInfo)
        {
            return E_OUTOFMEMORY;
        }

        if (!_pCurInfo->TakeOwn())
        {
            return E_OUTOFMEMORY;
        }

        NetApiBufferFree(info502);
    }
    else
    {
        appDebugOut((DEB_ERROR, "Couldn't get info\n"));
        return HRESULT_FROM_WIN32(ret);
    }

    return S_OK;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_PageProc, private
//
//  Synopsis:   Dialog Procedure for this object
//
//--------------------------------------------------------------------------

INT_PTR
CSharingPropertyPage::_PageProc(
    IN HWND hwnd,
    IN UINT msg,
    IN WPARAM wParam,
    IN LPARAM lParam
    )
{
    CHECK_SIG(CSharingPropertyPage);

    static DWORD aHelpIds[] =
    {
        IDC_SHARE_SHARENAME,        HC_SHARE_SHARENAME,
        IDC_SHARE_PATH,             HC_SHARE_PATH,
        IDC_SHARE_COMMENT,          HC_SHARE_COMMENT,
        IDC_SHARE_MAXIMUM,          HC_SHARE_MAXIMUM,
        IDC_SHARE_ALLOW,            HC_SHARE_ALLOW,
        IDC_SHARE_ALLOW_VALUE,      HC_SHARE_ALLOW_VALUE,
        IDC_SHARE_PERMISSIONS,      HC_SHARE_PERMISSIONS,

        0,0
    };

    switch (msg)
    {
    case WM_INITDIALOG:
        return _OnInitDialog(hwnd, (HWND)wParam, lParam);

    case WM_COMMAND:
        return _OnCommand(hwnd, HIWORD(wParam), LOWORD(wParam), (HWND)lParam);

    case WM_NOTIFY:
        return _OnNotify(hwnd, (int)wParam, (LPNMHDR)lParam);

    case WM_VSCROLL:
        // The up/down control changed the edit control: select it again
        SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
        return TRUE;

    case WM_HELP:
    {
        LPHELPINFO lphi = (LPHELPINFO)lParam;

        if (lphi->iContextType == HELPINFO_WINDOW)  // a control
        {
            WCHAR szHelp[50];
            LoadString(g_hInstance, IDS_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
            WinHelp(
                (HWND)lphi->hItemHandle,
                szHelp,
                HELP_WM_HELP,
                (DWORD_PTR)aHelpIds);
        }
        break;
    }

    case WM_CONTEXTMENU:
    {
        WCHAR szHelp[50];
        LoadString(g_hInstance, IDS_HELPFILENAME, szHelp, ARRAYLEN(szHelp));
        WinHelp(
            (HWND)wParam,
            szHelp,
            HELP_CONTEXTMENU,
            (DWORD_PTR)aHelpIds);
        break;
    }

    case WM_CLOSE:
        // BUGBUG: There is a bug where hitting "ESCAPE" with the focus on the
        // MLE for the "allow" text doesn't kill the property sheet unless we
        // forward the WM_CLOSE message on to the property sheet root dialog.
        return SendMessage(GetParent(hwnd), msg, wParam, lParam);

    case WM_DESTROY:
        // restore original subclass to window.
        appAssert(NULL != GetDlgItem(hwnd,IDC_SHARE_ALLOW_VALUE));
        SetWindowLongPtr(GetDlgItem(hwnd,IDC_SHARE_ALLOW_VALUE), GWLP_WNDPROC, (LONG_PTR)_pfnAllowProc);
        break;

    case WM_NCDESTROY:
        return _OnNcDestroy(hwnd);

    } // end switch (msg)

    return FALSE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnInitDialog, private
//
//  Synopsis:   WM_INITDIALOG handler
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnInitDialog(
    IN HWND hwnd,
    IN HWND hwndFocus,
    IN LPARAM lInitParam
    )
{
    CHECK_SIG(CSharingPropertyPage);
    appDebugOut((DEB_ITRACE, "_OnInitDialog\n"));

    SetDialogIconBig(_GetFrameWindow(), IDI_SHARESFLD);

    // Subclass allow edit control to disallow non-positive numbers
    _pfnAllowProc = (WNDPROC)SetWindowLongPtr(
                                    GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE),
                                    GWLP_WNDPROC,
                                    (LONG_PTR)&SizeWndProc);

    // use LanMan API constants to set maximum share name & comment lengths
    SendDlgItemMessage(hwnd, IDC_SHARE_SHARENAME, EM_LIMITTEXT, NNLEN, 0L);
    SendDlgItemMessage(hwnd, IDC_SHARE_PATH,      EM_LIMITTEXT, MAX_PATH-1, 0L);
    SendDlgItemMessage(hwnd, IDC_SHARE_COMMENT,   EM_LIMITTEXT, MAXCOMMENTSZ, 0L);

    _InitializeControls(hwnd);

// #if DBG == 1
//  Dump(L"_OnInitDialog finished");
// #endif // DBG == 1

    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnCommand, private
//
//  Synopsis:   WM_COMMAND handler
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnCommand(
    IN HWND hwnd,
    IN WORD wNotifyCode,
    IN WORD wID,
    IN HWND hwndCtl
    )
{
    CHECK_SIG(CSharingPropertyPage);

    switch (wID)
    {

//
// Notifications
//

    case IDC_SHARE_SHARENAME:
    {
        if (EN_CHANGE == wNotifyCode)
        {
            if (!_fInitializingPage)
            {
                _bShareNameChanged = TRUE;
                _MarkItemDirty();
            }
        }
        return TRUE;
    }

    case IDC_SHARE_PATH:
    {
        if (EN_CHANGE == wNotifyCode)
        {
            if (!_fInitializingPage)
            {
                _bPathChanged = TRUE;
                _MarkItemDirty();
            }
        }
        return TRUE;
    }

    case IDC_SHARE_COMMENT:
    {
        if (EN_CHANGE == wNotifyCode)
        {
            if (!_fInitializingPage)
            {
                _bCommentChanged = TRUE;
                _MarkItemDirty();
            }
        }
        return TRUE;
    }

    case IDC_SHARE_MAXIMUM:
        if (BN_CLICKED == wNotifyCode)
        {
            // Take away WS_TABSTOP from the "allow users" edit control
            HWND hwndEdit = GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE);
            SetWindowLong(hwndEdit, GWL_STYLE, GetWindowLong(hwndEdit, GWL_STYLE) & ~WS_TABSTOP);

            _CacheMaxUses(hwnd);
            SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");

            _bUserLimitChanged = TRUE;
            _MarkItemDirty();
        }
        return TRUE;

    case IDC_SHARE_ALLOW:
        if (BN_CLICKED == wNotifyCode)
        {
            // Give WS_TABSTOP to the "allow users" edit control
            HWND hwndEdit = GetDlgItem(hwnd, IDC_SHARE_ALLOW_VALUE);
            SetWindowLong(hwndEdit, GWL_STYLE, GetWindowLong(hwndEdit, GWL_STYLE) | WS_TABSTOP);

            // let the spin control set the edit control
            SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
            SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);

            _bUserLimitChanged = TRUE;
            _MarkItemDirty();
        }
        return TRUE;

    case IDC_SHARE_ALLOW_VALUE:
    {
        if (EN_CHANGE == wNotifyCode)
        {
            _bUserLimitChanged = TRUE;
            _MarkItemDirty();
        }

        if (EN_SETFOCUS == wNotifyCode)
        {
            if (1 != IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
            {
                CheckRadioButton(
                    hwnd,
                    IDC_SHARE_MAXIMUM,
                    IDC_SHARE_ALLOW,
                    IDC_SHARE_ALLOW);
            }

            // let the spin control set the edit control
            SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
            SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);

            _bUserLimitChanged = TRUE;
            _MarkItemDirty();
        }

        if (EN_KILLFOCUS == wNotifyCode)
        {
            _CacheMaxUses(hwnd);
        }

        return TRUE;
    }

    case IDC_SHARE_ALLOW_SPIN:
        if (UDN_DELTAPOS == wNotifyCode)
        {
            if (1 != IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
            {
                CheckRadioButton(
                    hwnd,
                    IDC_SHARE_MAXIMUM,
                    IDC_SHARE_ALLOW,
                    IDC_SHARE_ALLOW);
            }

            _bUserLimitChanged = TRUE;
            _MarkItemDirty();
        }
        return TRUE;

//
// Commands
//

    case IDC_SHARE_PERMISSIONS:
        return _OnPermissions(hwnd);

    default:
        break;
    }

    return FALSE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnNotify, private
//
//  Synopsis:   WM_NOTIFY handler
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnNotify(
    IN HWND hwnd,
    IN int idCtrl,
    IN LPNMHDR phdr
    )
{
    CHECK_SIG(CSharingPropertyPage);

    // assume a property sheet notification
    return _OnPropertySheetNotify(hwnd, phdr);
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnPropertySheetNotify, private
//
//  Synopsis:   WM_NOTIFY handler for the property sheet notification
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnPropertySheetNotify(
    IN HWND hwnd,
    IN LPNMHDR phdr
    )
{
    CHECK_SIG(CSharingPropertyPage);

    switch (phdr->code)
    {
    case PSN_RESET:         // cancel
        if (_DoCancel(hwnd))
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); // go away
        }
        else
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
        }
        return TRUE;

    case PSN_KILLACTIVE:    // change to another page
        if (_ValidatePage(hwnd))
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
            return FALSE;
        }
        else
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
            return TRUE;
        }

    case PSN_APPLY:
        if (_DoApply(hwnd))
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); // go away
        }
        else
        {
            SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
        }
        return TRUE;

    } // end switch (phdr->code)

    return FALSE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnNcDestroy, private
//
//  Synopsis:   WM_NCDESTROY handler
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnNcDestroy(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);

    delete this;    // do this LAST!
    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_OnPermissions, private
//
//  Synopsis:   WM_COMMAND handler: the permissions button
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_OnPermissions(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);
    appAssert(NULL != _pCurInfo);

    if (STYPE_SPECIAL & _pCurInfo->GetType())
    {
        MyErrorDialog(hwnd, IERR_AdminShare);
        return TRUE;
    }

    WCHAR szShareName[NNLEN + 1];
    GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
    // don't trim spaces, this might be an existing share with spaces in its name

    PSECURITY_DESCRIPTOR pNewSecDesc = NULL;
    PSECURITY_DESCRIPTOR pSecDesc = _pCurInfo->GetSecurityDescriptor();
    appAssert(NULL == pSecDesc || IsValidSecurityDescriptor(pSecDesc));

    BOOL bSecDescChanged;
    LONG err = EditShareAcl(
                        hwnd,
                        _pszMachine,
                        szShareName,
                        pSecDesc,
                        &bSecDescChanged,
                        &pNewSecDesc);

    if (bSecDescChanged)
    {
        _bSecDescChanged = TRUE;

        appAssert(IsValidSecurityDescriptor(pNewSecDesc));
        _pCurInfo->TransferSecurityDescriptor(pNewSecDesc);
        _MarkItemDirty();
    }

    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_InitializeControls, private
//
//  Synopsis:   Initialize the controls from scratch
//
//--------------------------------------------------------------------------

VOID
CSharingPropertyPage::_InitializeControls(
    IN HWND hwnd
    )
{
    _SetControlsToDefaults(hwnd);
    _SetControlsFromData(hwnd);
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_SetControlsToDefaults, private
//
//  Synopsis:   Set all the controls on the page to their default values
//
//--------------------------------------------------------------------------

VOID
CSharingPropertyPage::_SetControlsToDefaults(
    IN HWND hwnd
    )
{
    _fInitializingPage = TRUE;

    // Make "Maximum" the default number of users, and clear the value field
    // (which the spin button set on creation?).

    CheckRadioButton(
            hwnd,
            IDC_SHARE_MAXIMUM,
            IDC_SHARE_ALLOW,
            IDC_SHARE_MAXIMUM);

    SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");

    // set the spin control range: 1 <--> large number
    SendDlgItemMessage(
            hwnd,
            IDC_SHARE_ALLOW_SPIN,
            UDM_SETRANGE,
            0,
            MAKELONG(g_uiMaxUsers, 1));

    SetDlgItemText(hwnd, IDC_SHARE_SHARENAME,   L"");
    SetDlgItemText(hwnd, IDC_SHARE_PATH,        L"");
    SetDlgItemText(hwnd, IDC_SHARE_COMMENT,     L"");
    SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");

    _fInitializingPage = FALSE;
}



//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::SetControlsFromData, private
//
//  Synopsis:   From the class variables and current state of the radio
//              buttons, set the enabled/disabled state of the buttons, as
//              well as filling the controls with the appropriate values.
//
//--------------------------------------------------------------------------

VOID
CSharingPropertyPage::_SetControlsFromData(
    IN HWND hwnd
    )
{
    appAssert(NULL != _pCurInfo);

    _fInitializingPage = TRUE;

    SetDlgItemText(hwnd, IDC_SHARE_SHARENAME, _pCurInfo->GetNetname());
    SetDlgItemText(hwnd, IDC_SHARE_PATH,      _pCurInfo->GetPath());
    SetDlgItemText(hwnd, IDC_SHARE_COMMENT,   _pCurInfo->GetRemark());

    DWORD dwLimit = _pCurInfo->GetMaxUses();
    if (dwLimit == SHI_USES_UNLIMITED)
    {
        _wMaxUsers = DEFAULT_MAX_USERS;

        appDebugOut((DEB_ITRACE, "_SetControlsFromData: unlimited users\n"));

        CheckRadioButton(
                hwnd,
                IDC_SHARE_MAXIMUM,
                IDC_SHARE_ALLOW,
                IDC_SHARE_MAXIMUM);

        SetDlgItemText(hwnd, IDC_SHARE_ALLOW_VALUE, L"");
    }
    else
    {
        _wMaxUsers = (WORD)dwLimit;

        appDebugOut((DEB_ITRACE,
            "_SetControlsFromData: max users = %d\n",
            _wMaxUsers));

        CheckRadioButton(
                hwnd,
                IDC_SHARE_MAXIMUM,
                IDC_SHARE_ALLOW,
                IDC_SHARE_ALLOW);

        // let the spin control set the edit control
        SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));

        SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
    }

    // Managine a special share?
    if (_pCurInfo->GetType() & STYPE_SPECIAL)
    {
        // Can't change the path or the name
        // Making it read-only makes it easier to read than if it were disabled
        SendDlgItemMessage(hwnd, IDC_SHARE_SHARENAME, EM_SETREADONLY, (WPARAM)(BOOL)TRUE, 0);
        SendDlgItemMessage(hwnd, IDC_SHARE_PATH,      EM_SETREADONLY, (WPARAM)(BOOL)TRUE, 0);
    }

    _fInitializingPage = FALSE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_MarkItemDirty, private
//
//  Synopsis:   A change has made such that the current item (and page)
//              is now dirty
//
//--------------------------------------------------------------------------

VOID
CSharingPropertyPage::_MarkItemDirty(
    VOID
    )
{
    CHECK_SIG(CSharingPropertyPage);

    if (!_fInitializingPage)
    {
        if (!_bDirty)
        {
            appDebugOut((DEB_ITRACE, "Marking Sharing page dirty\n"));
            _bDirty = TRUE;
            PropSheet_Changed(_GetFrameWindow(),_hwndPage);
        }
    }
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_ValidatePage, private
//
//  Synopsis:   Return TRUE if the current page is valid
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_ValidatePage(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);
    appAssert(NULL != _pCurInfo);

    if (!_bDirty)
    {
        // nothing to validate
        return TRUE;
    }

    if (!_bShareNameChanged)
    {
        appDebugOut((DEB_ITRACE, "_ValidatePage: share name not changed!\n"));

        return TRUE;
    }

    delete[] _pszReplacePath;
    _pszReplacePath = NULL;

    WCHAR szShareName[MAX_PATH];
    GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
    TrimLeadingAndTrailingSpaces(szShareName);

    WCHAR szPath[MAX_PATH];
    GetDlgItemText(hwnd, IDC_SHARE_PATH, szPath, ARRAYLEN(szPath));

    // Validate the share

    if (0 == wcslen(szShareName))
    {
        MyErrorDialog(hwnd, IERR_BlankShareName);
        SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
        return FALSE;
    }

    HRESULT uTemp;
    if (!IsValidShareName(szShareName, &uTemp))
    {
        MyErrorDialog(hwnd, uTemp);
        SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
        return FALSE;
    }

    // Trying to create a reserved share?
    if (   (0 == _wcsicmp(g_szIpcShare,   szShareName))
        || (0 == _wcsicmp(g_szAdminShare, szShareName)))
    {
        MyErrorDialog(hwnd, IERR_SpecialShare);
        SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
        return FALSE;
    }

    // If the user entered some ACL, warn them that we're going to nuke
    // it and let the system use its default (since special shares can't
    // have their security set).
    if (DriveLetterShare(szShareName))
    {
        if (_bSecDescChanged)
        {
            DWORD id = MyConfirmationDialog(
                            hwnd,
                            MSG_NOSECURITYONSPECIAL,
                            MB_YESNO | MB_ICONEXCLAMATION);
            if (id == IDNO)
            {
                SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
                return FALSE;
            }
            _pCurInfo->TransferSecurityDescriptor(NULL);
        }
    }

    // Check for downlevel accessibility
    // CODEWORK we should really get rid of this at some point -- JonN 7/18/97
    ULONG nType;
    if (NERR_Success != NetpPathType(NULL, szShareName, &nType, INPT_FLAGS_OLDPATHS))
    {
        DWORD id = MyConfirmationDialog(
                        hwnd,
                        IERR_InaccessibleByDos,
                        MB_YESNO | MB_ICONEXCLAMATION,
                        szShareName);
        if (id == IDNO)
        {
            SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
            return FALSE;
        }
    }

    // Check to see that the same share isn't already used, for either the
    // same path or for another path.

    SHARE_INFO_502* info502;
    NET_API_STATUS ret = NetShareGetInfo(_pszMachine, szShareName, 502, (LPBYTE*)&info502);
    if (ret == NERR_Success)
    {
        // It is already shared. Same path?

        if (0 == _wcsicmp(info502->shi502_path, szPath))
        {
            MyErrorDialog(hwnd, IERR_AlreadyExists, szShareName);
            SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
            NetApiBufferFree(info502);
            return FALSE;
        }

        // Shared for a different path. Ask the user if they wish to delete
        // the old share and create the new one using the name.

        DWORD id = ConfirmReplaceShare(hwnd, szShareName, info502->shi502_path, szPath);
        if (id == IDNO)
        {
            SetErrorFocus(hwnd, IDC_SHARE_SHARENAME);
            NetApiBufferFree(info502);
            return FALSE;
        }
        else if (id == IDCANCEL)
        {
            // EndDialog(hwnd, FALSE);  // BUGBUG: nuke page
            NetApiBufferFree(info502);
            return TRUE;
        }
        else
        {
            _pszReplacePath = NewDup(info502->shi502_path);
            if (NULL == _pszReplacePath)
            {
                NetApiBufferFree(info502);
                MyErrorDialog(hwnd, E_OUTOFMEMORY);
                return FALSE;
            }
        }

        NetApiBufferFree(info502);
    }
    else
    {
        // NetShareGetInfo failed. This is probably because there
        // is no share by this name, in which case it is a pure rename.

        appDebugOut((DEB_TRACE,
            "NetShareGetInfo failed, 0x%08lx\n",
            ret));
    }

#if DBG == 1
    Dump(L"_ValidatePage finished");
#endif // DBG == 1

    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_DoApply, public
//
//  Synopsis:   If anything has changed, apply the data
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_DoApply(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);

    if (_bDirty)
    {
        appAssert(NULL != _pCurInfo);

        NET_API_STATUS ret;
        HRESULT hr;

        // If either the share name changed or the path changed, we need
        // to delete the old share. If the share name changed, it is
        // because the user is renaming the share. If the path changed,
        // it is because the LanMan APIs don't allow a NetShareSetInfo
        // to change the shared path.

        if (_bShareNameChanged)
        {
            // The share name was changed. This is either a pure rename, in
            // which case the old share should be deleted and a share with
            // the new name created, or the user changed the share name to
            // the name of an already existing share, in which case both the
            // current share name as well as the share to be replaced must be
            // deleted.

            if (NULL != _pszReplacePath)
            {
                // user said to replace an existing share
        		WCHAR szShareName[NNLEN + 1];
                GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
                TrimLeadingAndTrailingSpaces(szShareName);

                ret = NetShareDel(_pszMachine, szShareName, 0);
                if (ret != NERR_Success)
                {
                    DisplayError(hwnd, IERR_CANT_DEL_SHARE, ret, szShareName);
                    delete[] _pszReplacePath;
                    _pszReplacePath = NULL;
                    return FALSE;
                }
                else
                {
                    SHChangeNotify(SHCNE_NETUNSHARE, SHCNF_PATH, _pszReplacePath, NULL);
                }

                delete[] _pszReplacePath;
                _pszReplacePath = NULL;
            }
        }

        if (_bShareNameChanged || _bPathChanged)
        {
            // delete the existing share
            ret = NetShareDel(_pszMachine, _pCurInfo->GetNetname(), 0);
            if (ret != NERR_Success)
            {
                DisplayError(hwnd, IERR_CANT_DEL_SHARE, ret, _pCurInfo->GetNetname());
                return FALSE;
            }
            else
            {
                // Only if the path changed in the rename should the shell
                // be notified
                if (_bPathChanged)
                {
                    SHChangeNotify(SHCNE_NETUNSHARE, SHCNF_PATH, _pCurInfo->GetPath(), NULL);
                }
            }
        }

        if (_bShareNameChanged)
        {
            // User wants to rename the share.
        	WCHAR szShareName[NNLEN + 1];
            _pCurInfo->SetDirtyFlag(SHARE_FLAG_ADDED);   // special case
            GetDlgItemText(hwnd, IDC_SHARE_SHARENAME, szShareName, ARRAYLEN(szShareName));
            TrimLeadingAndTrailingSpaces(szShareName);
            _pCurInfo->SetNetname(szShareName);
        }

        if (_bPathChanged)
        {
			WCHAR szPath[MAX_PATH];
            _pCurInfo->SetDirtyFlag(SHARE_FLAG_ADDED);   // special case
            GetDlgItemText(hwnd, IDC_SHARE_PATH, szPath, ARRAYLEN(szPath));
            _pCurInfo->SetPath(szPath);
        }

        if (_bCommentChanged)
        {
        	WCHAR szComment[MAXCOMMENTSZ + 1];
            GetDlgItemText(hwnd, IDC_SHARE_COMMENT, szComment, ARRAYLEN(szComment));
            _pCurInfo->SetRemark(szComment);
        }

        if (_bUserLimitChanged)
        {
            if (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_MAXIMUM))
            {
                _pCurInfo->SetMaxUses(SHI_USES_UNLIMITED);
            }
            else if (1 == IsDlgButtonChecked(hwnd, IDC_SHARE_ALLOW))
            {
                _CacheMaxUses(hwnd);
                _pCurInfo->SetMaxUses(_wMaxUsers);
            }
        }

        //
        // Commit the changes!
        //

        ret = _pCurInfo->Commit(_pszMachine);
        if (ret != NERR_Success)
        {
            HRESULT hrMsg = 0;
            switch (_pCurInfo->GetFlag())
            {
            case SHARE_FLAG_ADDED:  hrMsg = IERR_CANT_ADD_SHARE;    break;
            case SHARE_FLAG_MODIFY: hrMsg = IERR_CANT_MODIFY_SHARE; break;
            default:
                appAssert(!"Illegal flag for a failed commit!");
            }
            DisplayError(hwnd, hrMsg, ret, _pCurInfo->GetNetname());
        }
        else
        {
            _pCurInfo->SetDirtyFlag(0);  // clear flag on success
        }

        _bDirty = FALSE;
        _bShareNameChanged = FALSE;
        _bPathChanged = FALSE;
        _bCommentChanged = FALSE;
        _bUserLimitChanged = FALSE;
        _bSecDescChanged = FALSE;
        PropSheet_UnChanged(_GetFrameWindow(),_hwndPage);

        SHChangeNotify(SHCNE_NETSHARE, SHCNF_PATH, _pCurInfo->GetPath(), NULL);

        _InitializeControls(hwnd);
    }

    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_DoCancel, public
//
//  Synopsis:   Do whatever is necessary to cancel the changes
//
//--------------------------------------------------------------------------

BOOL
CSharingPropertyPage::_DoCancel(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);

    if (_bDirty)
    {
        _bDirty = FALSE;
        _bShareNameChanged = FALSE;
        _bPathChanged = FALSE;
        _bCommentChanged = FALSE;
        _bUserLimitChanged = FALSE;
        _bSecDescChanged = FALSE;
        PropSheet_UnChanged(_GetFrameWindow(),_hwndPage);
    }

    return TRUE;
}


//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::_CacheMaxUses, private
//
//  Synopsis:
//
//--------------------------------------------------------------------------

VOID
CSharingPropertyPage::_CacheMaxUses(
    IN HWND hwnd
    )
{
    CHECK_SIG(CSharingPropertyPage);

    DWORD dwRet = (DWORD)SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_GETPOS, 0, 0);
    if (HIWORD(dwRet) != 0)
    {
        _wMaxUsers = DEFAULT_MAX_USERS;

        // Reset the edit control to the new value
        SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_SPIN, UDM_SETPOS, 0, MAKELONG(_wMaxUsers, 0));
        SendDlgItemMessage(hwnd, IDC_SHARE_ALLOW_VALUE, EM_SETSEL, 0, (LPARAM)-1);
    }
    else
    {
        _wMaxUsers = LOWORD(dwRet);
    }
}


#if DBG == 1

//+-------------------------------------------------------------------------
//
//  Method:     CSharingPropertyPage::Dump, private
//
//  Synopsis:
//
//--------------------------------------------------------------------------
VOID
CSharingPropertyPage::Dump(
    IN PWSTR pszCaption
    )
{
    CHECK_SIG(CSharingPropertyPage);

    appDebugOut((DEB_TRACE,
        "CSharingPropertyPage::Dump, %ws\n",
        pszCaption));

    appDebugOut((DEB_TRACE | DEB_NOCOMPNAME,
"\t            This: 0x%08lx\n"
"\t            Page: 0x%08lx\n"
"\t   Initializing?: %ws\n"
"\t          Dirty?: %ws\n"
"\t  Share changed?: %ws\n"
"\t   Path changed?: %ws\n"
"\tComment changed?: %ws\n"
"\tUsr Lim changed?: %ws\n"
"\t        Max uses: %d\n"
"\t       _pCurInfo: 0x%08lx\n"
,
this,
_hwndPage,
_fInitializingPage ? L"yes" : L"no",
_bDirty            ? L"yes" : L"no",
_bShareNameChanged ? L"yes" : L"no",
_bPathChanged      ? L"yes" : L"no",
_bCommentChanged   ? L"yes" : L"no",
_bUserLimitChanged ? L"yes" : L"no",
_wMaxUsers,
_pCurInfo
));

    _pCurInfo->Dump(L"Current");
}

#endif // DBG == 1
