Skip to content

src/local_secure_storage/impl/Windows.cpp

Namespaces

Name
sgns

Source code

#include "Windows.hpp"

#include <iostream>

#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

#include "windows.h"
#include "wincred.h"

namespace rj = rapidjson;

namespace sgns
{
    WindowsSecureStorage::WindowsSecureStorage( std::string identifier ) : identifier_( std::move( identifier ) ) {}

    outcome::result<rapidjson::Document> WindowsSecureStorage::LoadJSON() const
    {
        PCREDENTIALA p_cred;

        auto exists = CredReadA( identifier_.c_str(), CRED_TYPE_GENERIC, 0, &p_cred );

        if ( !exists )
        {
            auto error = GetLastError();
            if ( error == ERROR_NOT_FOUND )
            {
                rj::Document empty_document( rj::Type::kObjectType );
                return empty_document;
            }
            std::cerr << "Error loading secret: " << GetLastError() << '\n';
            return outcome::failure( std::errc::bad_message );
        }

        rj::Document d;
        d.Parse( reinterpret_cast<const char *>( p_cred->CredentialBlob ), p_cred->CredentialBlobSize );

        CredFree( p_cred );

        if ( d.HasParseError() || ( !d.IsObject() && !d.Empty() ) )
        {
            return outcome::failure( std::errc::bad_message );
        }

        return d;
    }

    outcome::result<void> WindowsSecureStorage::SaveJSON( rapidjson::Document document )
    {
        rj::StringBuffer password;
        rj::Writer       writer( password );
        document.Accept( writer );

        CREDENTIALA cred        = {};
        cred.Type               = CRED_TYPE_GENERIC;
        cred.TargetName         = const_cast<char*>(identifier_.c_str());
        cred.CredentialBlobSize = password.GetLength();
        cred.CredentialBlob     = reinterpret_cast<LPBYTE>( const_cast<char *>( password.GetString() ) );
        cred.Persist            = CRED_PERSIST_LOCAL_MACHINE;

        if ( !CredWriteA( &cred, 0 ) )
        {
            return outcome::failure( std::errc::bad_message );
        }

        return outcome::success();
    }
}

Updated on 2026-03-04 at 13:10:44 -0800