/*
    File:       Passwd.cpp

    Title:      Protected Storage User Confirm wrappers
    Author:     Matt Thomlinson
    Date:       2/25/97

    Passwd.cpp simply houses a few of the password-management
    functions. These functions are called on to return the
    user-confirmation derived buffer, and check synchronization
    in certain cases.

    As the Authentication provider interface gets defined, this
    could end up getting moved into a seperate provider.



*/

#include <pch.cpp>
#pragma hdrstop




#include "provui.h"
#include "storage.h"

#include "passwd.h"



extern              DISPIF_CALLBACKS    g_sCallbacks;
extern              PRIVATE_CALLBACKS   g_sPrivateCallbacks;
extern              CUAList*            g_pCUAList;


///////////////////////////////////////////////////////////////////////
// non-user editable passwords

BOOL FIsUserMasterKey(LPCWSTR szMasterKey)
{
    if (0 == wcscmp(szMasterKey, WSZ_PASSWORD_WINDOWS))
        return FALSE;

    return TRUE;
}

BOOL    FMyGetWinPassword(
    PST_PROVIDER_HANDLE* phPSTProv,
    LPCWSTR szUser,
    BYTE rgbPwd[A_SHA_DIGEST_LEN] )
{
    // nab pwd
    if (0 == wcscmp(szUser, WSZ_LOCAL_MACHINE))
    {
        CopyMemory(rgbPwd, RGB_LOCALMACHINE_KEY, A_SHA_DIGEST_LEN);
    }
    else
    {
 /*
        if (! g_sPrivateCallbacks.pfnFGetWindowsPassword(
                phPSTProv,
                rgbPwd,
                A_SHA_DIGEST_LEN))
            return FALSE;
  */
        A_SHA_CTX context;
        DWORD cb = lstrlenW(szUser) * sizeof(WCHAR);
        BYTE Magic1[] = {0x66, 0x41, 0xa3, 0x29};
        BYTE Magic2[] = {0x14, 0x9a, 0xef, 0x82};

        A_SHAInit(&context);
        // note: the three Update calls get buffered up internally to
        // multiples of 64 bytes.
        //
        A_SHAUpdate(&context, Magic1, sizeof(Magic1));
        A_SHAUpdate(&context, (LPBYTE)szUser, cb);
        A_SHAUpdate(&context, Magic2, (cb+sizeof(Magic2)) % sizeof(Magic2));
        A_SHAFinal(&context, rgbPwd);
    }

    return TRUE;
}

// Base Provider specific fxn: check the password
DWORD BPVerifyPwd(
    PST_PROVIDER_HANDLE*    phPSTProv,
    LPCWSTR                 szUser,
    LPCWSTR                 szMasterKey,
    BYTE                    rgbPwd[],
    DWORD                   dwPasswordOption)
{
    DWORD dwRet = (DWORD)PST_E_WRONG_PASSWORD;

    if (dwPasswordOption != BP_CONFIRM_PASSWORDUI)
    {
        // only non-user keys can be silent (WinPWs only, to be exact)
        if (FIsUserMasterKey(szMasterKey))
            goto Ret;

        // get the Windows pwd
        if (!FMyGetWinPassword(phPSTProv, szUser, rgbPwd))
            goto Ret;

        // check
        if (!FCheckPWConfirm(
                szUser,
                szMasterKey,
                rgbPwd))
        {
            dwRet = (DWORD)PST_E_WRONG_PASSWORD;
            goto Ret;
        }
    }
    else    // UI wanted
    {
        // is it the windows password?
        if (0 == wcscmp(szMasterKey, WSZ_PASSWORD_WINDOWS))
        {
            BYTE rgbWinPwd[A_SHA_DIGEST_LEN];

            // we need to keep user, WinPW in sync
            if(!FMyGetWinPassword(
                    phPSTProv,
                    szUser,
                    rgbWinPwd
                    ))
            {
                dwRet = (DWORD)PST_E_WRONG_PASSWORD;
                goto Ret;
            }

            if (0 != memcmp(rgbWinPwd, rgbPwd, sizeof(rgbWinPwd) ))
            {
                // no match: user entered old password?
                if (FCheckPWConfirm(
                        szUser,
                        szMasterKey,
                        rgbPwd))
                {
                    // err: user entered neither old nor new password
                    dwRet = (DWORD)PST_E_WRONG_PASSWORD;
                    goto Ret;
                }
            }
            else
            {
                // matched: user entered password we consider good
                if (!FCheckPWConfirm(
                        szUser,
                        szMasterKey,
                        rgbPwd))
                {
                    dwRet = (DWORD)PST_E_WRONG_PASSWORD;
                    goto Ret;
                }
            }

        }
        else
        {
            // else: not win pw, just do pw correctness check
            if (!FCheckPWConfirm(
                    szUser,
                    szMasterKey,
                    rgbPwd))
            {
                dwRet = (DWORD)PST_E_WRONG_PASSWORD;
                goto Ret;
            }
        }
    }

    dwRet = (DWORD)PST_E_OK;
Ret:
    return dwRet;
}


HRESULT GetUserConfirmDefaults(
    PST_PROVIDER_HANDLE*    phPSTProv,
    DWORD*                  pdwDefaultConfirmationStyle,
    LPWSTR*                 ppszMasterKey)
{
    SS_ASSERT(ppszMasterKey != NULL);
    SS_ASSERT(pdwDefaultConfirmationStyle != NULL);

    PBYTE pbData = NULL;
    DWORD cbData;
    HRESULT hr = PST_E_FAIL;

    // if not found, restore the machine defaults

    // alloc sizeof string + dword
    cbData = sizeof(WSZ_PASSWORD_WINDOWS) + sizeof(DWORD);
    pbData = (PBYTE)SSAlloc(cbData);
    if(pbData == NULL)
        return PST_E_FAIL;

    // copy string, DWORD confirmation type
    *(DWORD*)pbData = BP_CONFIRM_OKCANCEL;
    CopyMemory(pbData+sizeof(DWORD), WSZ_PASSWORD_WINDOWS, sizeof(WSZ_PASSWORD_WINDOWS));

    // format: confirmation style DWORD, sz
    *pdwDefaultConfirmationStyle = *(DWORD*)pbData;
    *ppszMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT((LPWSTR)(pbData+sizeof(DWORD))));

    if(*ppszMasterKey != NULL) {
        wcscpy(*ppszMasterKey, (LPWSTR) (pbData+sizeof(DWORD)) );
        hr = PST_E_OK;
    }

    // free what ConfigData returned
    if (pbData)
        SSFree(pbData);

    return hr;
}


void NotifyOfWrongPassword(
            HWND hwnd,
            LPCWSTR szItemName,
            LPCWSTR szPasswordName)
{
    LPWSTR szMessage;

    if (0 == wcscmp(szPasswordName, WSZ_PASSWORD_WINDOWS))
        szMessage = g_PasswordWinNoVerify;
    else
        szMessage = g_PasswordNoVerify;     // error doesn't deal with win pw

    MessageBoxW(hwnd, szMessage, szItemName, MB_OK | MB_SERVICE_NOTIFICATION);
}

// #define to force an unreadable confirmation to bail from read proc
#define PST_CF_STORED_ONLY  0xcf000001

HRESULT GetUserConfirmBuf(
    PST_PROVIDER_HANDLE*    phPSTProv,
    LPCWSTR                 szUser,
    PST_KEY                 Key,
    LPCWSTR                 szType,
    const GUID*             pguidType,
    LPCWSTR                 szSubtype,
    const GUID*             pguidSubtype,
    LPCWSTR                 szItemName,
    PPST_PROMPTINFO         psPrompt,
    LPCWSTR                 szAction,
    LPWSTR*                 ppszMasterKey,
    BYTE                    rgbPwd[A_SHA_DIGEST_LEN],
    DWORD                   dwFlags)
{
    return GetUserConfirmBuf(
        phPSTProv,
        szUser,
        Key,
        szType,
        pguidType,
        szSubtype,
        pguidSubtype,
        szItemName,
        psPrompt,
        szAction,
        PST_CF_STORED_ONLY,        // hardcoded: must be able to retreive in order to show ui
        ppszMasterKey,
        rgbPwd,
        dwFlags);
}

#define MAX_PASSWD_TRIALS 3

HRESULT GetUserConfirmBuf(
    PST_PROVIDER_HANDLE*    phPSTProv,
    LPCWSTR                 szUser,
    PST_KEY                 Key,
    LPCWSTR                 szType,
    const GUID*             pguidType,
    LPCWSTR                 szSubtype,
    const GUID*             pguidSubtype,
    LPCWSTR                 szItemName,
    PPST_PROMPTINFO         psPrompt,
    LPCWSTR                 szAction,
    DWORD                   dwDefaultConfirmationStyle,
    LPWSTR*                 ppszMasterKey,
    BYTE                    rgbOutPwd[A_SHA_DIGEST_LEN],
    DWORD                   dwFlags)
{
    HRESULT     hr;
    DWORD       dwStoredConfirm, dwChosenConfirm;
    LPWSTR      szCallerName = NULL;
    BOOL        fPromptedUser = FALSE;

    BOOL        fIsCached = FALSE;
    BOOL        fCacheItNow = FALSE;

    BOOL        fPwdVerified = FALSE;

    SS_ASSERT(*ppszMasterKey == NULL);   // don't whack existing memory


    if (Key == PST_KEY_LOCAL_MACHINE)
    {
        // short-circuit password gathering, setting
        *ppszMasterKey = (LPWSTR) SSAlloc(sizeof(WSZ_PASSWORD_WINDOWS));
        if( *ppszMasterKey == NULL )
        {
            hr = PST_E_FAIL;
            goto Ret;
        }

        wcscpy(*ppszMasterKey, WSZ_PASSWORD_WINDOWS);

        CopyMemory(rgbOutPwd, RGB_LOCALMACHINE_KEY, A_SHA_DIGEST_LEN);

        // done
        hr = PST_E_OK;
        goto Ret;
    }


    if (!g_sCallbacks.pfnFGetCallerName(phPSTProv, &szCallerName, NULL)) {
        hr = PST_E_FAIL;
        goto Ret;
    }

    // Which is this: item creation, item access?
    // item access does user authentication
    SS_ASSERT(szItemName != NULL);

    // per-item key
    if (PST_E_OK != (hr =
        BPGetItemConfirm(
            phPSTProv,
            szUser,
            pguidType,
            pguidSubtype,
            szItemName,
            &dwStoredConfirm,
            ppszMasterKey)) )
    {
        // this could be a failure in
        // * confirmation: tampering detected!!
        // * password: couldn't grab user pwd
        if (dwDefaultConfirmationStyle == PST_CF_STORED_ONLY)
            goto Ret;

        //
        // if UI is not allowed (eg, Local System account), over-ride
        // confirmation style.
        //
        if (dwDefaultConfirmationStyle != PST_CF_NONE)
        {
            if(!FIsProviderUIAllowed( szUser ))
                dwDefaultConfirmationStyle = PST_CF_NONE;
        }

        // if app asked to have no confirm, set item that way
        if (dwDefaultConfirmationStyle == PST_CF_NONE)
        {
            dwChosenConfirm = BP_CONFIRM_NONE;

            // short-circuit password gathering, setting
            *ppszMasterKey = (LPWSTR) SSAlloc(sizeof(WSZ_PASSWORD_WINDOWS));
            if(*ppszMasterKey == NULL)
            {
                hr = PST_E_FAIL;
                goto Ret;
            }
            wcscpy(*ppszMasterKey, WSZ_PASSWORD_WINDOWS);
        }
        else    // app allows user to decide
        {
            // get user default
            if (PST_E_OK != (hr = GetUserConfirmDefaults(
                    phPSTProv,
                    &dwChosenConfirm,
                    ppszMasterKey)) )
                goto Ret;
        }

        // if user default is silent, don't bother user
        switch(dwChosenConfirm)
        {
            // if no confirm
            case BP_CONFIRM_NONE:
                break;

            // if we know the confirm type
            case BP_CONFIRM_PASSWORDUI:
            {
                // make sure we're not asking the user for a password he can't satisfy
                if (!FIsUserMasterKey(*ppszMasterKey))
                {
                    hr = PST_E_NO_PERMISSIONS;
                    goto Ret;
                }

                // else fall through to prompting case
            }

            case BP_CONFIRM_OKCANCEL:
            {
                int i;
                fPromptedUser = TRUE;

                for(i=1;  ; i++)
                {
                    BYTE rgbOutPwdLowerCase[A_SHA_DIGEST_LEN];

                    // Request the user apply a new password
                    if (!FSimplifiedPasswordConfirm(
                            phPSTProv,
                            szUser,
                            szCallerName,
                            szType,
                            szSubtype,
                            szItemName,
                            psPrompt,
                            szAction,
                            ppszMasterKey,
                            &dwChosenConfirm,
                            TRUE,           // user select which pwd
                            rgbOutPwd,
                            A_SHA_DIGEST_LEN,
                            rgbOutPwdLowerCase,
                            A_SHA_DIGEST_LEN,
                            dwFlags
                            ))
                    {
                        hr = PST_E_NO_PERMISSIONS;
                        goto Ret;
                    }

                    // verify whatever password we got
                    if (PST_E_OK != (hr =
                        BPVerifyPwd(
                            phPSTProv,
                            szUser,
                            *ppszMasterKey,
                            rgbOutPwd,
                            dwChosenConfirm)) )
                    {

                        //
                        // try lower-case form to handle Win9x migration case.
                        //

                        if (PST_E_OK != (hr =
                            BPVerifyPwd(
                                phPSTProv,
                                szUser,
                                *ppszMasterKey,
                                rgbOutPwdLowerCase,
                                dwChosenConfirm)) )
                        {
                            // too many trials? break out of loop
                            if (i < MAX_PASSWD_TRIALS)
                            {
                                // notify user, give them another chance
                                NotifyOfWrongPassword((HWND)psPrompt->hwndApp, szItemName, *ppszMasterKey);

                                continue;
                            } else {
                                break;  // break out
                            }
                        } else {

                            CopyMemory( rgbOutPwd, rgbOutPwdLowerCase, A_SHA_DIGEST_LEN );

                        }
                    }

                    // passed verify password test: break out of loop!
                    fPwdVerified = TRUE;
                    break;
                }

                if (!fPwdVerified)
                {
                    hr = PST_E_NO_PERMISSIONS;
                    goto Ret;
                }
            }
        }


        // and remember the selections made
        if (PST_E_OK != (hr =
            BPSetItemConfirm(
                phPSTProv,
                szUser,
                pguidType,
                pguidSubtype,
                szItemName,
                dwChosenConfirm,
                *ppszMasterKey)) )
            goto Ret;

        // now, _this_ is the stored confirm
        dwStoredConfirm = dwChosenConfirm;
    }
    else
    {
        // keep a copy of the stored key
        LPWSTR szStoredMasterKey = (LPWSTR)SSAlloc(WSZ_BYTECOUNT(*ppszMasterKey));
        if(NULL != szStoredMasterKey)
        {
            CopyMemory(szStoredMasterKey, *ppszMasterKey, WSZ_BYTECOUNT(*ppszMasterKey));
        }

        // we retrieved confirmation behavior
        dwChosenConfirm = dwStoredConfirm;  // already chosen for you

        switch (dwStoredConfirm)
        {
            // if no confirm
            case BP_CONFIRM_NONE:
                break;

            // if we know the confirm type
            case BP_CONFIRM_PASSWORDUI:
            {
                // else fall through to prompting case
            }

            case BP_CONFIRM_OKCANCEL:
            {
                // retrieved item, must show ui, but not allowed to show ui
                if (psPrompt->dwPromptFlags & PST_PF_NEVER_SHOW)
                {
                    hr = ERROR_PASSWORD_RESTRICTION;
                    goto Ret;
                }

                // found that a pwd is req'd
                fPromptedUser = TRUE;
                fCacheItNow = fIsCached;

                int i;

                for(i=1;  ; i++)
                {
                    BYTE rgbOutPwdLowerCase[A_SHA_DIGEST_LEN];

                    // ask the user for it
                    if (!FSimplifiedPasswordConfirm(
                            phPSTProv,
                            szUser,
                            szCallerName,
                            szType,
                            szSubtype,
                            szItemName,
                            psPrompt,
                            szAction,
                            ppszMasterKey,
                            &dwChosenConfirm,
                            TRUE,           // allow user to select pwd
                            rgbOutPwd,
                            A_SHA_DIGEST_LEN,
                            rgbOutPwdLowerCase,
                            A_SHA_DIGEST_LEN,
                            dwFlags
                            ))
                    {
                        hr = PST_E_NO_PERMISSIONS;
                        goto Ret;
                    }

                    // if we got it from the cache and user left it alone
                    {
                        // verify whatever password we got
                        if (PST_E_OK != (hr =
                            BPVerifyPwd(
                                phPSTProv,
                                szUser,
                                *ppszMasterKey,
                                rgbOutPwd,
                                dwChosenConfirm)) )
                        {
                            //
                            // check lower case form.
                            //

                            if (PST_E_OK != (hr =
                                BPVerifyPwd(
                                    phPSTProv,
                                    szUser,
                                    *ppszMasterKey,
                                    rgbOutPwdLowerCase,
                                    dwChosenConfirm)) )
                            {

                                // too many trials? break out of loop
                                if (i < MAX_PASSWD_TRIALS)
                                {
                                    // notify user, give them another chance
                                    NotifyOfWrongPassword((HWND)psPrompt->hwndApp, szItemName, *ppszMasterKey);

                                    continue;
                                }
                                else
                                {
                                    hr = PST_E_NO_PERMISSIONS;
                                    goto Ret;
                                }
                            } else {

                                CopyMemory( rgbOutPwd, rgbOutPwdLowerCase, A_SHA_DIGEST_LEN );
                            }
                        }

                        fPwdVerified = TRUE;
                    }

                    // passed verify password test: break out of loop!
                    break;
                }

                break;
            }

        } // end switch


        // have we received all data we need from the user?
        // user may choose to change the way items are encrypted;
        // if stored under password, we must make them enter the old pwd
        if ((dwStoredConfirm != dwChosenConfirm) ||                     // confirm type changed  OR
            (NULL == szStoredMasterKey) || 
            (0 != wcscmp(*ppszMasterKey, szStoredMasterKey)) )          // difft master key

        {
            BYTE rgbOldPwd[A_SHA_DIGEST_LEN];
            BOOL fDontAllowCache = FALSE;
            BOOL fOldPwdVerified = FALSE;

            PST_PROMPTINFO         sGetOldPWPrompt = {sizeof(PST_PROMPTINFO), psPrompt->dwPromptFlags, psPrompt->hwndApp, g_PasswordSolicitOld};

            // only re-display if originally passworded
            if (dwStoredConfirm == BP_CONFIRM_PASSWORDUI)
            {
                for(int i=1;  ; i++)
                {
                    BYTE rgbOldPwdLowerCase[A_SHA_DIGEST_LEN];

                    // ask the user for it
                    if (!FSimplifiedPasswordConfirm(
                            phPSTProv,
                            szUser,
                            szCallerName,
                            szType,
                            szSubtype,
                            szItemName,
                            &sGetOldPWPrompt,
                            szAction,
                            &szStoredMasterKey,
                            &dwStoredConfirm,
                            FALSE,           // don't allow user to get around this one
                            rgbOldPwd,
                            sizeof(rgbOldPwd),
                            rgbOldPwdLowerCase,
                            sizeof(rgbOldPwdLowerCase),
                            dwFlags
                            ))
                    {
                        hr = PST_E_NO_PERMISSIONS;
                        goto Ret;
                    }

                    // verify whatever password we got
                    if (PST_E_OK != (hr =
                        BPVerifyPwd(
                            phPSTProv,
                            szUser,
                            szStoredMasterKey,
                            rgbOldPwd,
                            dwStoredConfirm)) )
                    {
                        if (PST_E_OK != (hr =
                            BPVerifyPwd(
                                phPSTProv,
                                szUser,
                                szStoredMasterKey,
                                rgbOldPwdLowerCase,
                                dwStoredConfirm)) )
                        {
                            // too many trials? break out of loop
                            if (i < MAX_PASSWD_TRIALS)
                            {
                                // notify user, give them another chance
                                NotifyOfWrongPassword((HWND)sGetOldPWPrompt.hwndApp, szItemName, szStoredMasterKey);

                                continue;
                            } else {
                                break;  // break out
                            }
                        } else {
                            CopyMemory( rgbOldPwd, rgbOldPwdLowerCase, A_SHA_DIGEST_LEN );
                        }
                    }

                    // passed verify password test: break out of loop!
                    fOldPwdVerified = TRUE;
                    break;
                }

                if (!fOldPwdVerified)
                {
                    hr = PST_E_NO_PERMISSIONS;
                    goto Ret;
                }
            }
            else
            {
                // ok/cancel; silent pwd usage

                // use VerifyPwd fxn to retrieve the pwd
                if (PST_E_OK != (hr =
                    BPVerifyPwd(
                        phPSTProv,
                        szUser,
                        szStoredMasterKey,
                        rgbOldPwd,
                        dwStoredConfirm)) )
                {
                    hr = PST_E_NO_PERMISSIONS;
                    goto Ret;
                }
            }

            //////
            // execute pwd change HERE
            {
                PBYTE pbData = NULL;
                DWORD cbData;

                // FBPGetSecuredItemData        // decrypt data with old
                if (!FBPGetSecuredItemData(
                        szUser,
                        szStoredMasterKey,
                        rgbOldPwd,
                        pguidType,
                        pguidSubtype,
                        szItemName,
                        &pbData,
                        &cbData))
                {
                    hr = PST_E_STORAGE_ERROR;
                    goto Ret;
                }

                // FBPSetSecuredItemData        // encrypt data with new
                if (!FBPSetSecuredItemData(
                        szUser,
                        *ppszMasterKey,
                        rgbOutPwd,
                        pguidType,
                        pguidSubtype,
                        szItemName,
                        pbData,
                        cbData))
                {
                    hr = PST_E_STORAGE_ERROR;
                    goto Ret;
                }

                if (pbData)
                    SSFree(pbData);

                // BPSetItemConfirm             // store new confirm type
                if (PST_E_OK !=
                    BPSetItemConfirm(
                        phPSTProv,
                        szUser,
                        pguidType,
                        pguidSubtype,
                        szItemName,
                        dwChosenConfirm,
                        *ppszMasterKey))
                {
                    hr = PST_E_STORAGE_ERROR;
                    goto Ret;
                }
            }

        }


        if (szStoredMasterKey)
        {
            SSFree(szStoredMasterKey);
            szStoredMasterKey = NULL;
        }
    }



    // verify whatever password we got if not yet verified
    if (!fPwdVerified)
    {
        if (PST_E_OK != (hr =
            BPVerifyPwd(
                phPSTProv,
                szUser,
                *ppszMasterKey,
                rgbOutPwd,
                dwChosenConfirm)) )
            goto Ret;
    }

    // Now correct pwd is in rgbOutPwd ALWAYS

    // if we haven't prompted user and were supposed to
    if (!fPromptedUser && (psPrompt->dwPromptFlags == PST_PF_ALWAYS_SHOW))
    {
        // we must've retrieved from cache OR Automagic WinPW
        SS_ASSERT(fIsCached || (BP_CONFIRM_NONE == dwStoredConfirm));

        BYTE rgbBarfPwd[A_SHA_DIGEST_LEN*2];
        BYTE rgbBarfPwdLowerCase[A_SHA_DIGEST_LEN];

        // haven't prompted user but must confirm
        if (!FSimplifiedPasswordConfirm(
                phPSTProv,
                szUser,
                szCallerName,
                szType,
                szSubtype,
                szItemName,
                psPrompt,
                szAction,
                ppszMasterKey,
                &dwChosenConfirm,
                FALSE,
                rgbBarfPwd,
                sizeof(rgbBarfPwd),
                rgbBarfPwdLowerCase,
                sizeof(rgbBarfPwdLowerCase),
                dwFlags
                ) )
        {
            hr = PST_E_NO_PERMISSIONS;
            goto Ret;
        }

    }

    hr = PST_E_OK;
Ret:

    if (szCallerName)
        SSFree(szCallerName);

    return hr;
}



HRESULT ShowOKCancelUI(
    PST_PROVIDER_HANDLE*    phPSTProv,
    LPCWSTR                 szUser,
    PST_KEY                 Key,
    LPCWSTR                 szType,
    LPCWSTR                 szSubtype,
    LPCWSTR                 szItemName,
    PPST_PROMPTINFO         psPrompt,
    LPCWSTR                 szAction)
{
    BOOL fCache = FALSE;
    BYTE rgbTrash[A_SHA_DIGEST_LEN*2];
    BYTE rgbTrashLowerCase[A_SHA_DIGEST_LEN];
    DWORD dwConfirmOptions = BP_CONFIRM_OKCANCEL;

    LPWSTR szMasterKey = NULL;
    LPWSTR szCallerName = NULL;

    DWORD dwRet = PST_E_FAIL;

    if (Key == PST_KEY_LOCAL_MACHINE)
    {
        // done
        dwRet = PST_E_OK;
        goto Ret;
    }

    szMasterKey = (LPWSTR)SSAlloc(sizeof(WSZ_NULLSTRING));

    if(szMasterKey)
    {
        wcscpy(szMasterKey, WSZ_NULLSTRING);
    }

    if (!g_sCallbacks.pfnFGetCallerName(phPSTProv, &szCallerName, NULL))
        goto Ret;

    if (!FSimplifiedPasswordConfirm(
            phPSTProv,
            szUser,
            szCallerName,
            szType,
            szSubtype,
            szItemName,
            psPrompt,
            szAction,
            &szMasterKey,
            &dwConfirmOptions,
            FALSE,
            rgbTrash,
            sizeof(rgbTrash),
            rgbTrashLowerCase,
            sizeof(rgbTrashLowerCase),
            0
            ) )
        goto Ret;

    dwRet = PST_E_OK;
Ret:
    if (szCallerName)
        SSFree(szCallerName);

    if (szMasterKey)
        SSFree(szMasterKey);

    return dwRet;
}