diff --git a/Sources/Plasma/FeatureLib/CMakeLists.txt b/Sources/Plasma/FeatureLib/CMakeLists.txt
index 5faa5ada..39acaf4a 100644
--- a/Sources/Plasma/FeatureLib/CMakeLists.txt
+++ b/Sources/Plasma/FeatureLib/CMakeLists.txt
@@ -18,6 +18,7 @@ add_subdirectory(pfJournalBook)
add_subdirectory(pfLocalizationMgr)
add_subdirectory(pfMessage)
add_subdirectory(pfMoviePlayer)
+add_subdirectory(pfPasswordStore)
add_subdirectory(pfPatcher)
add_subdirectory(pfPython)
add_subdirectory(pfSurface)
diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt
new file mode 100644
index 00000000..2ab83c4e
--- /dev/null
+++ b/Sources/Plasma/FeatureLib/pfPasswordStore/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories("../../CoreLib")
+include_directories("../../NucleusLib")
+include_directories("../../NucleusLib/inc")
+include_directories("../../PubUtilLib")
+
+set(pfPasswordStore_HEADERS
+ pfPasswordStore.h
+ pfPasswordStore_impl.h
+)
+
+set(pfPasswordStore_SOURCES
+ pfPasswordStore.cpp
+)
+
+add_library(pfPasswordStore STATIC ${pfPasswordStore_HEADERS} ${pfPasswordStore_SOURCES})
+target_link_libraries(pfPasswordStore CoreLib plFile)
+
+source_group("Header Files" FILES ${pfPasswordStore_HEADERS})
+source_group("Source Files" FILES ${pfPasswordStore_SOURCES})
+
diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp
new file mode 100644
index 00000000..b3faeae4
--- /dev/null
+++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.cpp
@@ -0,0 +1,196 @@
+/*==LICENSE==*
+
+CyanWorlds.com Engine - MMOG client, server and tools
+Copyright (C) 2011 Cyan Worlds, Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+Additional permissions under GNU GPL version 3 section 7
+
+If you modify this Program, or any covered work, by linking or
+combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
+NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
+JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
+(or a modified version of those libraries),
+containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
+PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
+JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
+licensors of this Program grant you additional
+permission to convey the resulting work. Corresponding Source for a
+non-source form of such a combination shall include the source code for
+the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
+work.
+
+You can contact Cyan Worlds, Inc. by email legal@cyan.com
+ or by snail mail at:
+ Cyan Worlds, Inc.
+ 14617 N Newport Hwy
+ Mead, WA 99021
+
+*==LICENSE==*/
+
+#include "pfPasswordStore.h"
+#include "pfPasswordStore_impl.h"
+
+#include "plProduct.h"
+#include "plFile/plEncryptedStream.h"
+
+/* Get the pfPasswordStore instance */
+pfPasswordStore* pfPasswordStore::Instance()
+{
+ static pfPasswordStore* store = nullptr;
+
+ if (store == nullptr) {
+#ifdef HS_BUILD_FOR_WIN32
+ store = new pfWin32PasswordStore();
+#else
+ store = new pfFilePasswordStore();
+#endif
+ }
+
+ return store;
+}
+
+
+
+/*****************************************************************************
+ ** pfFilePasswordStore **
+ *****************************************************************************/
+
+pfFilePasswordStore::pfFilePasswordStore()
+{
+ // TODO: Cross-platform CryptKey initialization
+ uint32_t* product = (uint32_t*)plProduct::UUID();
+ for (int i = 0; i < 4; i++) {
+ fCryptKey[i] = product[i];
+ }
+}
+
+
+const plString pfFilePasswordStore::GetPassword(const plString& username)
+{
+ plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat");
+ plString password = plString::Null;
+
+#ifndef PLASMA_EXTERNAL_RELEASE
+ // internal builds can use the local init directory
+ plFileName local("init\\login.dat");
+ if (plFileInfo(local).Exists())
+ loginDat = local;
+#endif
+
+ hsStream* stream = plEncryptedStream::OpenEncryptedFile(loginDat, fCryptKey);
+ if (stream && !stream->AtEnd())
+ {
+ uint32_t savedKey[4];
+ stream->Read(sizeof(savedKey), savedKey);
+
+ if (memcmp(fCryptKey, savedKey, sizeof(savedKey)) == 0 && !stream->AtEnd())
+ {
+ plString uname = stream->ReadSafeString();
+ if (username.CompareI(uname) == 0) {
+ password = stream->ReadSafeString();
+ }
+ }
+
+ stream->Close();
+ delete stream;
+ }
+
+ return password;
+}
+
+
+bool pfFilePasswordStore::SetPassword(const plString& username, const plString& password)
+{
+ plFileName loginDat = plFileName::Join(plFileSystem::GetInitPath(), "login.dat");
+
+#ifndef PLASMA_EXTERNAL_RELEASE
+ // internal builds can use the local init directory
+ plFileName local("init\\login.dat");
+ if (plFileInfo(local).Exists())
+ loginDat = local;
+#endif
+
+ hsStream* stream = plEncryptedStream::OpenEncryptedFileWrite(loginDat, fCryptKey);
+ if (stream)
+ {
+ stream->Write(sizeof(fCryptKey), fCryptKey);
+ stream->WriteSafeString(username);
+ stream->WriteSafeString(password);
+
+ stream->Close();
+ delete stream;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+
+#ifdef HS_BUILD_FOR_WIN32
+#include
+
+/*****************************************************************************
+ ** pfWin32PasswordStore **
+ *****************************************************************************/
+const plString pfWin32PasswordStore::GetPassword(const plString& username)
+{
+ PCREDENTIALW credential;
+ plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str());
+ plString password = plString::Null;
+
+ if (!CredReadW(target.ToUtf16(), CRED_TYPE_GENERIC, 0, &credential)) {
+ return password;
+ }
+
+ password = plString::FromUtf16((uint16_t*)credential->CredentialBlob, credential->CredentialBlobSize);
+
+ memset(credential->CredentialBlob, 0, credential->CredentialBlobSize);
+ CredFree(credential);
+
+ return password;
+}
+
+
+bool pfWin32PasswordStore::SetPassword(const plString& username, const plString& password)
+{
+ CREDENTIALW credential;
+ plString target = plString::Format("%s__%s", plProduct::UUID(), username.c_str());
+
+ if (password.IsNull()) {
+ if (CredDeleteW(target.ToUtf16(), CRED_TYPE_GENERIC, 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ memset(&credential, 0, sizeof(CREDENTIALW));
+ credential.Type = CRED_TYPE_GENERIC;
+ credential.TargetName = target.ToUtf16();
+ credential.CredentialBlobSize = password.GetSize();
+ credential.CredentialBlob = (LPBYTE)password.ToUtf16();
+ credential.Persist = CRED_PERSIST_LOCAL_MACHINE;
+ credential.UserName = username.ToUtf16();
+
+ if (!CredWriteW(&credential, 0)) {
+ return false;
+ }
+
+ return true;
+}
+#endif
diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h
new file mode 100644
index 00000000..fd794ba2
--- /dev/null
+++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore.h
@@ -0,0 +1,59 @@
+/*==LICENSE==*
+
+CyanWorlds.com Engine - MMOG client, server and tools
+Copyright (C) 2011 Cyan Worlds, Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+Additional permissions under GNU GPL version 3 section 7
+
+If you modify this Program, or any covered work, by linking or
+combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
+NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
+JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
+(or a modified version of those libraries),
+containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
+PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
+JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
+licensors of this Program grant you additional
+permission to convey the resulting work. Corresponding Source for a
+non-source form of such a combination shall include the source code for
+the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
+work.
+
+You can contact Cyan Worlds, Inc. by email legal@cyan.com
+ or by snail mail at:
+ Cyan Worlds, Inc.
+ 14617 N Newport Hwy
+ Mead, WA 99021
+
+*==LICENSE==*/
+
+#ifndef pfPasswordStore_inc
+#define pfPasswordStore_inc
+
+#include "HeadSpin.h"
+#include "plString.h"
+
+class pfPasswordStore
+{
+public:
+ static pfPasswordStore* Instance();
+
+
+ virtual const plString GetPassword(const plString& username) = 0;
+ virtual bool SetPassword(const plString& username, const plString& password) = 0;
+};
+
+#endif //pfPasswordStore_inc
diff --git a/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h
new file mode 100644
index 00000000..ebbe0a08
--- /dev/null
+++ b/Sources/Plasma/FeatureLib/pfPasswordStore/pfPasswordStore_impl.h
@@ -0,0 +1,83 @@
+/*==LICENSE==*
+
+CyanWorlds.com Engine - MMOG client, server and tools
+Copyright (C) 2011 Cyan Worlds, Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+Additional permissions under GNU GPL version 3 section 7
+
+If you modify this Program, or any covered work, by linking or
+combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
+NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
+JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
+(or a modified version of those libraries),
+containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
+PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
+JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
+licensors of this Program grant you additional
+permission to convey the resulting work. Corresponding Source for a
+non-source form of such a combination shall include the source code for
+the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
+work.
+
+You can contact Cyan Worlds, Inc. by email legal@cyan.com
+ or by snail mail at:
+ Cyan Worlds, Inc.
+ 14617 N Newport Hwy
+ Mead, WA 99021
+
+*==LICENSE==*/
+
+#ifndef pfPasswordStore_impl_inc
+#define pfPasswordStore_impl_inc
+
+#include "pfPasswordStore.h"
+
+/**
+ * An encrypted file-based password storage mechanism.
+ */
+class pfFilePasswordStore : public pfPasswordStore
+{
+private:
+ uint32_t fCryptKey[4];
+
+public:
+ pfFilePasswordStore();
+
+ virtual const plString GetPassword(const plString& username);
+ virtual bool SetPassword(const plString& username, const plString& password);
+};
+
+
+#ifdef HS_BUILD_FOR_WIN32
+/**
+ * A Windows Credential Vault password storage mechanism.
+ */
+class pfWin32PasswordStore : public pfPasswordStore
+{
+public:
+ pfWin32PasswordStore() { }
+
+ virtual const plString GetPassword(const plString& username);
+ virtual bool SetPassword(const plString& username, const plString& password);
+};
+#endif //HS_BUILD_FOR_WIN32
+
+
+// TODO: A Linux libsecret-based storage mechanism
+
+// TODO: An OSX KeyChain-based storage mechanism
+
+#endif //pfPasswordStore_impl_inc