2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIPassword.h"
12 #include "GUIUserMessages.h"
13 #include "ServiceBroker.h"
15 #include "dialogs/GUIDialogGamepad.h"
16 #include "dialogs/GUIDialogNumeric.h"
17 #include "favourites/FavouritesService.h"
18 #include "guilib/GUIComponent.h"
19 #include "guilib/GUIKeyboardFactory.h"
20 #include "guilib/GUIWindowManager.h"
21 #include "guilib/LocalizeStrings.h"
22 #include "media/MediaLockState.h"
23 #include "messaging/ApplicationMessenger.h"
24 #include "messaging/helpers/DialogOKHelper.h"
25 #include "profiles/ProfileManager.h"
26 #include "profiles/dialogs/GUIDialogLockSettings.h"
27 #include "profiles/dialogs/GUIDialogProfileSettings.h"
28 #include "settings/MediaSourceSettings.h"
29 #include "settings/Settings.h"
30 #include "settings/SettingsComponent.h"
31 #include "utils/StringUtils.h"
32 #include "utils/URIUtils.h"
33 #include "utils/Variant.h"
34 #include "utils/log.h"
35 #include "view/ViewStateSettings.h"
39 using namespace KODI::MESSAGING
;
41 CGUIPassword::CGUIPassword(void)
43 iMasterLockRetriesLeft
= -1;
46 CGUIPassword::~CGUIPassword(void) = default;
49 bool CGUIPassword::IsItemUnlocked(T pItem
,
50 const std::string
& strType
,
51 const std::string
& strLabel
,
52 const std::string
& strHeading
)
54 const std::shared_ptr
<CProfileManager
> profileManager
=
55 CServiceBroker::GetSettingsComponent()->GetProfileManager();
56 if (profileManager
->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
)
59 while (pItem
->m_iHasLock
> LOCK_STATE_LOCK_BUT_UNLOCKED
)
61 const std::string strLockCode
= pItem
->m_strLockCode
;
62 int iResult
= 0; // init to user succeeded state, doing this to optimize switch statement below
63 if (!g_passwordManager
.bMasterUser
) // Check if we are the MasterUser!
65 if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
66 CSettings::SETTING_MASTERLOCK_MAXRETRIES
) &&
67 pItem
->m_iBadPwdCount
>= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
68 CSettings::SETTING_MASTERLOCK_MAXRETRIES
))
70 // user previously exhausted all retries, show access denied error
71 HELPERS::ShowOKDialogText(CVariant
{12345}, CVariant
{12346});
74 // show the appropriate lock dialog
75 iResult
= VerifyPassword(pItem
->m_iLockMode
, strLockCode
, strHeading
);
80 { // user canceled out
86 // password entry succeeded
87 pItem
->m_iBadPwdCount
= 0;
88 pItem
->m_iHasLock
= LOCK_STATE_LOCK_BUT_UNLOCKED
;
89 g_passwordManager
.LockSource(strType
, strLabel
, false);
90 CMediaSourceSettings::GetInstance().UpdateSource(strType
, strLabel
, "badpwdcount",
91 std::to_string(pItem
->m_iBadPwdCount
));
92 CMediaSourceSettings::GetInstance().Save();
94 // a mediasource has been unlocked successfully
95 // => refresh favourites due to possible visibility changes
96 CServiceBroker::GetFavouritesService().RefreshFavourites();
101 // password entry failed
102 if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
103 CSettings::SETTING_MASTERLOCK_MAXRETRIES
))
104 pItem
->m_iBadPwdCount
++;
105 CMediaSourceSettings::GetInstance().UpdateSource(strType
, strLabel
, "badpwdcount",
106 std::to_string(pItem
->m_iBadPwdCount
));
107 CMediaSourceSettings::GetInstance().Save();
112 // this should never happen, but if it does, do nothing
121 bool CGUIPassword::IsItemUnlocked(CFileItem
* pItem
, const std::string
& strType
)
123 const std::string strLabel
= pItem
->GetLabel();
124 std::string strHeading
;
125 if (pItem
->m_bIsFolder
)
126 strHeading
= g_localizeStrings
.Get(12325); // "Locked! Enter code..."
128 strHeading
= g_localizeStrings
.Get(12348); // "Item locked"
130 return IsItemUnlocked
<CFileItem
*>(pItem
, strType
, strLabel
, strHeading
);
133 bool CGUIPassword::IsItemUnlocked(CMediaSource
* pItem
, const std::string
& strType
)
135 const std::string strLabel
= pItem
->strName
;
136 const std::string
& strHeading
= g_localizeStrings
.Get(12325); // "Locked! Enter code..."
138 return IsItemUnlocked
<CMediaSource
*>(pItem
, strType
, strLabel
, strHeading
);
141 bool CGUIPassword::CheckStartUpLock()
143 // prompt user for mastercode if the mastercode was set b4 or by xml
144 int iVerifyPasswordResult
= -1;
146 const std::string
& strHeader
= g_localizeStrings
.Get(20075); // "Enter master lock code"
148 if (iMasterLockRetriesLeft
== -1)
149 iMasterLockRetriesLeft
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES
);
151 if (g_passwordManager
.iMasterLockRetriesLeft
== 0)
152 g_passwordManager
.iMasterLockRetriesLeft
= 1;
154 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
156 std::string strPassword
= profileManager
->GetMasterProfile().getLockCode();
158 if (profileManager
->GetMasterProfile().getLockMode() == 0)
159 iVerifyPasswordResult
= 0;
162 for (int i
=1; i
<= g_passwordManager
.iMasterLockRetriesLeft
; i
++)
164 iVerifyPasswordResult
= VerifyPassword(profileManager
->GetMasterProfile().getLockMode(), strPassword
, strHeader
);
165 if (iVerifyPasswordResult
!= 0 )
167 std::string strLabel1
;
168 strLabel1
= g_localizeStrings
.Get(12343); // "retries left"
169 int iLeft
= g_passwordManager
.iMasterLockRetriesLeft
-i
;
170 std::string strLabel
= StringUtils::Format("{} {}", iLeft
, strLabel1
);
172 // PopUp OK and Display: MasterLock mode has changed but no new Mastercode has been set!
173 HELPERS::ShowOKDialogLines(CVariant
{12360}, CVariant
{12367}, CVariant
{strLabel
}, CVariant
{""});
176 i
=g_passwordManager
.iMasterLockRetriesLeft
;
180 if (iVerifyPasswordResult
== 0)
182 g_passwordManager
.iMasterLockRetriesLeft
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES
);
183 return true; // OK The MasterCode Accepted! XBMC Can Run!
187 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_SHUTDOWN
); // Turn off the box
192 bool CGUIPassword::SetMasterLockMode(bool bDetails
)
194 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
196 CProfile
* profile
= profileManager
->GetProfile(0);
199 CProfile::CLock locks
= profile
->GetLocks();
200 // prompt user for master lock
201 if (CGUIDialogLockSettings::ShowAndGetLock(locks
, 12360, true, bDetails
))
203 profile
->SetLocks(locks
);
210 bool CGUIPassword::IsProfileLockUnlocked(int iProfile
)
213 return IsProfileLockUnlocked(iProfile
,bDummy
,true);
216 bool CGUIPassword::IsProfileLockUnlocked(int iProfile
, bool& bCanceled
, bool prompt
)
218 if (g_passwordManager
.bMasterUser
)
221 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
223 int iProfileToCheck
= iProfile
;
225 iProfileToCheck
= profileManager
->GetCurrentProfileIndex();
227 if (iProfileToCheck
== 0)
228 return IsMasterLockUnlocked(prompt
,bCanceled
);
231 const CProfile
*profile
= profileManager
->GetProfile(iProfileToCheck
);
236 return (profile
->getLockMode() == LOCK_MODE_EVERYONE
);
238 if (profile
->getDate().empty() &&
239 (profileManager
->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
||
240 profile
->getLockMode() == LOCK_MODE_EVERYONE
))
242 // user hasn't set a password and this is the first time they've used this account
243 // so prompt for password/settings
244 if (CGUIDialogProfileSettings::ShowForProfile(iProfileToCheck
, true))
249 if (profileManager
->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE
)
250 // prompt user for profile lock code
251 return CheckLock(profile
->getLockMode(),profile
->getLockCode(),20095,bCanceled
);
258 bool CGUIPassword::IsMasterLockUnlocked(bool bPromptUser
)
261 return IsMasterLockUnlocked(bPromptUser
,bDummy
);
264 bool CGUIPassword::IsMasterLockUnlocked(bool bPromptUser
, bool& bCanceled
)
268 if (iMasterLockRetriesLeft
== -1)
269 iMasterLockRetriesLeft
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES
);
271 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
273 if ((LOCK_MODE_EVERYONE
< profileManager
->GetMasterProfile().getLockMode() && !bMasterUser
) && !bPromptUser
)
275 // not unlocked, but calling code doesn't want to prompt user
279 if (g_passwordManager
.bMasterUser
|| profileManager
->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
)
282 if (iMasterLockRetriesLeft
== 0)
284 UpdateMasterLockRetryCount(false);
288 // no, unlock since we are allowed to prompt
289 const std::string
& strHeading
= g_localizeStrings
.Get(20075);
290 std::string strPassword
= profileManager
->GetMasterProfile().getLockCode();
292 int iVerifyPasswordResult
= VerifyPassword(profileManager
->GetMasterProfile().getLockMode(), strPassword
, strHeading
);
293 if (1 == iVerifyPasswordResult
)
294 UpdateMasterLockRetryCount(false);
296 if (0 != iVerifyPasswordResult
)
302 // user successfully entered mastercode
303 UpdateMasterLockRetryCount(true);
307 void CGUIPassword::UpdateMasterLockRetryCount(bool bResetCount
)
309 // \brief Updates Master Lock status.
310 // \param bResetCount masterlock retry counter is zeroed if true, or incremented and displays an Access Denied dialog if false.
313 // Bad mastercode entered
314 if (0 < CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES
))
316 // We're keeping track of how many bad passwords are entered
317 if (1 < g_passwordManager
.iMasterLockRetriesLeft
)
319 // user still has at least one retry after decrementing
320 g_passwordManager
.iMasterLockRetriesLeft
--;
324 // user has run out of retry attempts
325 g_passwordManager
.iMasterLockRetriesLeft
= 0;
326 // Tell the user they ran out of retry attempts
327 HELPERS::ShowOKDialogText(CVariant
{12345}, CVariant
{12346});
331 std::string dlgLine1
= "";
332 if (0 < g_passwordManager
.iMasterLockRetriesLeft
)
333 dlgLine1
= StringUtils::Format("{} {}", g_passwordManager
.iMasterLockRetriesLeft
,
334 g_localizeStrings
.Get(12343)); // "retries left"
335 // prompt user for master lock code
336 HELPERS::ShowOKDialogLines(CVariant
{20075}, CVariant
{12345}, CVariant
{std::move(dlgLine1
)}, CVariant
{0});
339 g_passwordManager
.iMasterLockRetriesLeft
= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES
); // user entered correct mastercode, reset retries to max allowed
342 bool CGUIPassword::CheckLock(LockType btnType
, const std::string
& strPassword
, int iHeading
)
345 return CheckLock(btnType
,strPassword
,iHeading
,bDummy
);
348 bool CGUIPassword::CheckLock(LockType btnType
, const std::string
& strPassword
, int iHeading
, bool& bCanceled
)
352 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
354 if (btnType
== LOCK_MODE_EVERYONE
||
355 strPassword
== "-" ||
356 profileManager
->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
||
357 g_passwordManager
.bMasterUser
)
362 const std::string
& strHeading
= g_localizeStrings
.Get(iHeading
);
363 int iVerifyPasswordResult
= VerifyPassword(btnType
, strPassword
, strHeading
);
365 if (iVerifyPasswordResult
== -1)
368 return (iVerifyPasswordResult
==0);
371 bool CGUIPassword::CheckSettingLevelLock(const SettingLevel
& level
, bool enforce
/*=false*/)
373 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
375 LOCK_LEVEL::SETTINGS_LOCK lockLevel
= profileManager
->GetCurrentProfile().settingsLockLevel();
377 if (lockLevel
== LOCK_LEVEL::NONE
)
380 //check if we are already in settings and in an level that needs unlocking
381 int windowID
= CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
382 if ((int)lockLevel
-1 <= (short)CViewStateSettings::GetInstance().GetSettingLevel() &&
383 (windowID
== WINDOW_SETTINGS_MENU
||
384 (windowID
>= WINDOW_SCREEN_CALIBRATION
&&
385 windowID
<= WINDOW_SETTINGS_MYPVR
)))
386 return true; //Already unlocked
388 else if (lockLevel
== LOCK_LEVEL::ALL
)
389 return IsMasterLockUnlocked(true);
390 else if ((int)lockLevel
-1 <= (short)level
)
393 return IsMasterLockUnlocked(true);
394 else if (!IsMasterLockUnlocked(false))
396 //Current Setting level is higher than our permission... so lower the viewing level
397 SettingLevel newLevel
= (SettingLevel
)(short)(lockLevel
-2);
398 CViewStateSettings::GetInstance().SetSettingLevel(newLevel
);
405 bool IsSettingsWindow(int iWindowID
)
407 return (iWindowID
>= WINDOW_SCREEN_CALIBRATION
&& iWindowID
<= WINDOW_SETTINGS_MYPVR
)
408 || iWindowID
== WINDOW_SKIN_SETTINGS
;
411 bool CGUIPassword::CheckMenuLock(int iWindowID
)
413 bool bCheckPW
= false;
414 int iSwitch
= iWindowID
;
416 // check if a settings subcategory was called from other than settings window
417 if (IsSettingsWindow(iWindowID
))
419 int iCWindowID
= CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
420 if (iCWindowID
!= WINDOW_SETTINGS_MENU
&& !IsSettingsWindow(iCWindowID
))
421 iSwitch
= WINDOW_SETTINGS_MENU
;
424 if (iWindowID
== WINDOW_MUSIC_NAV
)
426 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_HOME
)
427 iSwitch
= WINDOW_MUSIC_NAV
;
430 if (iWindowID
== WINDOW_VIDEO_NAV
)
432 if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_HOME
)
433 iSwitch
= WINDOW_VIDEO_NAV
;
436 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
440 case WINDOW_SETTINGS_MENU
: // Settings
441 return CheckSettingLevelLock(CViewStateSettings::GetInstance().GetSettingLevel());
443 case WINDOW_ADDON_BROWSER
: // Addons
444 bCheckPW
= profileManager
->GetCurrentProfile().addonmanagerLocked();
446 case WINDOW_FILES
: // Files
447 bCheckPW
= profileManager
->GetCurrentProfile().filesLocked();
449 case WINDOW_PROGRAMS
: // Programs
450 bCheckPW
= profileManager
->GetCurrentProfile().programsLocked();
452 case WINDOW_MUSIC_NAV
: // Music
453 bCheckPW
= profileManager
->GetCurrentProfile().musicLocked();
454 if (!bCheckPW
&& !m_strMediaSourcePath
.empty()) // check mediasource by path
455 return g_passwordManager
.IsMediaPathUnlocked(profileManager
, "music");
457 case WINDOW_VIDEO_NAV
: // Video
458 bCheckPW
= profileManager
->GetCurrentProfile().videoLocked();
459 if (!bCheckPW
&& !m_strMediaSourcePath
.empty()) // check mediasource by path
460 return g_passwordManager
.IsMediaPathUnlocked(profileManager
, "video");
462 case WINDOW_PICTURES
: // Pictures
463 bCheckPW
= profileManager
->GetCurrentProfile().picturesLocked();
465 case WINDOW_GAMES
: // Games
466 bCheckPW
= profileManager
->GetCurrentProfile().gamesLocked();
468 case WINDOW_SETTINGS_PROFILES
:
476 return IsMasterLockUnlocked(true); //Now let's check the PW if we need!
481 bool CGUIPassword::LockSource(const std::string
& strType
, const std::string
& strName
, bool bState
)
483 VECSOURCES
* pShares
= CMediaSourceSettings::GetInstance().GetSources(strType
);
484 bool bResult
= false;
485 for (IVECSOURCES it
=pShares
->begin();it
!= pShares
->end();++it
)
487 if (it
->strName
== strName
)
489 if (it
->m_iHasLock
> LOCK_STATE_NO_LOCK
)
491 it
->m_iHasLock
= bState
? LOCK_STATE_LOCKED
: LOCK_STATE_LOCK_BUT_UNLOCKED
;
497 CGUIMessage
msg(GUI_MSG_NOTIFY_ALL
,0,0,GUI_MSG_UPDATE_SOURCES
);
498 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg
);
503 void CGUIPassword::LockSources(bool lock
)
505 // lock or unlock all sources (those with locks)
506 const char* strTypes
[] = {"programs", "music", "video", "pictures", "files", "games"};
507 for (const char* const strType
: strTypes
)
509 VECSOURCES
*shares
= CMediaSourceSettings::GetInstance().GetSources(strType
);
510 for (IVECSOURCES it
=shares
->begin();it
!= shares
->end();++it
)
511 if (it
->m_iLockMode
!= LOCK_MODE_EVERYONE
)
512 it
->m_iHasLock
= lock
? LOCK_STATE_LOCKED
: LOCK_STATE_LOCK_BUT_UNLOCKED
;
514 CGUIMessage
msg(GUI_MSG_NOTIFY_ALL
,0,0,GUI_MSG_UPDATE_SOURCES
);
515 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg
);
518 void CGUIPassword::RemoveSourceLocks()
520 // remove lock from all sources
521 const char* strTypes
[] = {"programs", "music", "video", "pictures", "files", "games"};
522 for (const char* const strType
: strTypes
)
524 VECSOURCES
*shares
= CMediaSourceSettings::GetInstance().GetSources(strType
);
525 for (IVECSOURCES it
=shares
->begin();it
!= shares
->end();++it
)
526 if (it
->m_iLockMode
!= LOCK_MODE_EVERYONE
) // remove old info
528 it
->m_iHasLock
= LOCK_STATE_NO_LOCK
;
529 it
->m_iLockMode
= LOCK_MODE_EVERYONE
;
531 // remove locks from xml
532 CMediaSourceSettings::GetInstance().UpdateSource(strType
, it
->strName
, "lockmode", "0");
535 CMediaSourceSettings::GetInstance().Save();
536 CGUIMessage
msg(GUI_MSG_NOTIFY_ALL
,0,0, GUI_MSG_UPDATE_SOURCES
);
537 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg
);
540 bool CGUIPassword::IsDatabasePathUnlocked(const std::string
& strPath
, VECSOURCES
& vecSources
)
542 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
544 if (g_passwordManager
.bMasterUser
|| profileManager
->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE
)
547 // try to find the best matching source
549 int iIndex
= CUtil::GetMatchingSource(strPath
, vecSources
, bName
);
551 if (iIndex
> -1 && iIndex
< static_cast<int>(vecSources
.size()))
552 if (vecSources
[iIndex
].m_iHasLock
< LOCK_STATE_LOCKED
)
558 bool CGUIPassword::IsMediaPathUnlocked(const std::shared_ptr
<CProfileManager
>& profileManager
,
559 const std::string
& strType
) const
561 if (!StringUtils::StartsWithNoCase(m_strMediaSourcePath
, "root") &&
562 !StringUtils::StartsWithNoCase(m_strMediaSourcePath
, "library://"))
564 if (!g_passwordManager
.bMasterUser
&&
565 profileManager
->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE
)
567 VECSOURCES
& vecSources
= *CMediaSourceSettings::GetInstance().GetSources(strType
);
569 int iIndex
= CUtil::GetMatchingSource(m_strMediaSourcePath
, vecSources
, bName
);
570 if (iIndex
> -1 && iIndex
< static_cast<int>(vecSources
.size()))
572 return g_passwordManager
.IsItemUnlocked(&vecSources
[iIndex
], strType
);
580 bool CGUIPassword::IsMediaFileUnlocked(const std::string
& type
, const std::string
& file
) const
582 std::vector
<CMediaSource
>* vecSources
= CMediaSourceSettings::GetInstance().GetSources(type
);
587 "{}: CMediaSourceSettings::GetInstance().GetSources(\"{}\") returned nullptr.",
592 // try to find the best matching source for this file
594 bool isSourceName
{false};
595 const std::string fileBasePath
= URIUtils::GetBasePath(file
);
597 int iIndex
= CUtil::GetMatchingSource(fileBasePath
, *vecSources
, isSourceName
);
599 if (iIndex
> -1 && iIndex
< static_cast<int>(vecSources
->size()))
600 return (*vecSources
)[iIndex
].m_iHasLock
< LOCK_STATE_LOCKED
;
605 void CGUIPassword::OnSettingAction(const std::shared_ptr
<const CSetting
>& setting
)
610 const std::string
&settingId
= setting
->GetId();
611 if (settingId
== CSettings::SETTING_MASTERLOCK_LOCKCODE
)
615 int CGUIPassword::VerifyPassword(LockType btnType
, const std::string
& strPassword
, const std::string
& strHeading
)
617 int iVerifyPasswordResult
;
620 case LOCK_MODE_NUMERIC
:
621 iVerifyPasswordResult
= CGUIDialogNumeric::ShowAndVerifyPassword(const_cast<std::string
&>(strPassword
), strHeading
, 0);
623 case LOCK_MODE_GAMEPAD
:
624 iVerifyPasswordResult
= CGUIDialogGamepad::ShowAndVerifyPassword(const_cast<std::string
&>(strPassword
), strHeading
, 0);
626 case LOCK_MODE_QWERTY
:
627 iVerifyPasswordResult
= CGUIKeyboardFactory::ShowAndVerifyPassword(const_cast<std::string
&>(strPassword
), strHeading
, 0);
629 default: // must not be supported, treat as unlocked
630 iVerifyPasswordResult
= 0;
634 return iVerifyPasswordResult
;