// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSUtilities.h"
#include "Utility.h"
#include <cstdint>
#include <cstdio>
#include <unordered_map>
#include <condition_variable>
#include <mutex>

// DebugView: filter on "[ANSAWS]" or "[ANSUTIL]" — gated by ANSCORE_DEBUGVIEW in ANSLicense.h.

// ── ANSUtilities handle registry ──
// destructionStarted: set by the first Unregister caller; blocks new Acquires
// and causes subsequent Unregister calls to return false without deleting.
// Prevents double-free when two threads race Release on the same handle.
struct UtilEntry { int refcount; bool destructionStarted; };
static std::unordered_map<ANSCENTER::ANSUtilities*, UtilEntry>& UtilHandleRegistry() {
    static std::unordered_map<ANSCENTER::ANSUtilities*, UtilEntry> s;
    return s;
}
static std::mutex& UtilHandleRegistryMutex() {
    static std::mutex m;
    return m;
}
static std::condition_variable& UtilHandleRegistryCV() {
    static std::condition_variable cv;
    return cv;
}

static void RegisterUtilHandle(ANSCENTER::ANSUtilities* h) {
    std::lock_guard<std::mutex> lk(UtilHandleRegistryMutex());
    UtilHandleRegistry()[h] = { 1, false };
    ANS_DBG("ANSUTIL","Register: handle=%p (uint=%llu) registrySize=%zu",
           (void*)h, (unsigned long long)(uintptr_t)h, UtilHandleRegistry().size());
}

static ANSCENTER::ANSUtilities* AcquireUtilHandle(ANSCENTER::ANSUtilities* h) {
    std::lock_guard<std::mutex> lk(UtilHandleRegistryMutex());
    auto it = UtilHandleRegistry().find(h);
    if (it == UtilHandleRegistry().end()) {
        ANS_DBG("ANSUTIL","Acquire FAIL: handle=%p (uint=%llu) NOT in registry. registrySize=%zu",
               (void*)h, (unsigned long long)(uintptr_t)h, UtilHandleRegistry().size());
        size_t i = 0;
        for (auto& kv : UtilHandleRegistry()) {
            ANS_DBG("ANSUTIL","  registry[%zu] = %p (uint=%llu) refcount=%d destructionStarted=%d",
                   i++, (void*)kv.first, (unsigned long long)(uintptr_t)kv.first,
                   kv.second.refcount, kv.second.destructionStarted ? 1 : 0);
        }
        return nullptr;
    }
    if (it->second.destructionStarted) {
        ANS_DBG("ANSUTIL","Acquire FAIL: handle=%p is being destroyed (destructionStarted=true)", (void*)h);
        return nullptr;
    }
    it->second.refcount++;
    ANS_DBG("ANSUTIL","Acquire OK:   handle=%p refcount=%d", (void*)h, it->second.refcount);
    return h;
}

static bool ReleaseUtilHandleRef(ANSCENTER::ANSUtilities* h) {
    std::lock_guard<std::mutex> lk(UtilHandleRegistryMutex());
    auto it = UtilHandleRegistry().find(h);
    if (it == UtilHandleRegistry().end()) return false;
    it->second.refcount--;
    if (it->second.refcount <= 0) {
        UtilHandleRegistryCV().notify_all();
    }
    return false;  // Only Unregister deletes. Ref drop just signals the CV.
}

static bool UnregisterUtilHandle(ANSCENTER::ANSUtilities* h) {
    std::unique_lock<std::mutex> lk(UtilHandleRegistryMutex());
    auto it = UtilHandleRegistry().find(h);
    if (it == UtilHandleRegistry().end()) {
        ANS_DBG("ANSUTIL","Unregister: handle=%p NOT in registry (already gone)", (void*)h);
        return false;
    }
    if (it->second.destructionStarted) {
        // Another thread is already tearing this handle down; let it own the delete.
        ANS_DBG("ANSUTIL","Unregister: handle=%p already being destroyed by another thread, returning false", (void*)h);
        return false;
    }
    ANS_DBG("ANSUTIL","Unregister: handle=%p starting (refcount before=%d)", (void*)h, it->second.refcount);
    it->second.destructionStarted = true;
    it->second.refcount--;
    bool ok = UtilHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
        auto it2 = UtilHandleRegistry().find(h);
        return it2 == UtilHandleRegistry().end() || it2->second.refcount <= 0;
    });
    if (!ok) {
        ANS_DBG("ANSUTIL","WARNING: Unregister timed out waiting for in-flight operations on handle=%p", (void*)h);
        OutputDebugStringA("WARNING: UnregisterUtilHandle timed out waiting for in-flight operations\n");
    }
    UtilHandleRegistry().erase(h);
    return true;
}

class UtilHandleGuard {
    ANSCENTER::ANSUtilities* engine;
public:
    explicit UtilHandleGuard(ANSCENTER::ANSUtilities* e) : engine(e) {}
    ~UtilHandleGuard() { if (engine) ReleaseUtilHandleRef(engine); }
    ANSCENTER::ANSUtilities* get() const { return engine; }
    explicit operator bool() const { return engine != nullptr; }
    UtilHandleGuard(const UtilHandleGuard&) = delete;
    UtilHandleGuard& operator=(const UtilHandleGuard&) = delete;
};

// ── ANSAWSS3 handle registry ──
// destructionStarted: set by the first Unregister caller; blocks new Acquires
// and causes subsequent Unregister calls to return false without deleting.
// Prevents double-free when two threads race Release on the same handle
// (e.g. LabVIEW double-Release on the same wire, or Release during heap reuse).
struct AWSEntry { int refcount; bool destructionStarted; };
static std::unordered_map<ANSCENTER::ANSAWSS3*, AWSEntry>& AWSHandleRegistry() {
    static std::unordered_map<ANSCENTER::ANSAWSS3*, AWSEntry> s;
    return s;
}
static std::mutex& AWSHandleRegistryMutex() {
    static std::mutex m;
    return m;
}
static std::condition_variable& AWSHandleRegistryCV() {
    static std::condition_variable cv;
    return cv;
}

static void RegisterAWSHandle(ANSCENTER::ANSAWSS3* h) {
    std::lock_guard<std::mutex> lk(AWSHandleRegistryMutex());
    AWSHandleRegistry()[h] = { 1, false };
    ANS_DBG("ANSAWS", "Register: handle=%p (uint=%llu) registrySize=%zu",
           (void*)h, (unsigned long long)(uintptr_t)h, AWSHandleRegistry().size());
}

static bool IsAWSHandleLive(ANSCENTER::ANSAWSS3* h) {
    std::lock_guard<std::mutex> lk(AWSHandleRegistryMutex());
    auto it = AWSHandleRegistry().find(h);
    return it != AWSHandleRegistry().end() && !it->second.destructionStarted;
}

static ANSCENTER::ANSAWSS3* AcquireAWSHandle(ANSCENTER::ANSAWSS3* h) {
    std::lock_guard<std::mutex> lk(AWSHandleRegistryMutex());
    auto it = AWSHandleRegistry().find(h);
    if (it == AWSHandleRegistry().end()) {
        ANS_DBG("ANSAWS", "Acquire FAIL: handle=%p (uint=%llu) NOT in registry. registrySize=%zu",
               (void*)h, (unsigned long long)(uintptr_t)h, AWSHandleRegistry().size());
        size_t i = 0;
        for (auto& kv : AWSHandleRegistry()) {
            ANS_DBG("ANSAWS", "  registry[%zu] = %p (uint=%llu) refcount=%d destructionStarted=%d",
                   i++, (void*)kv.first, (unsigned long long)(uintptr_t)kv.first,
                   kv.second.refcount, kv.second.destructionStarted ? 1 : 0);
        }
        return nullptr;
    }
    if (it->second.destructionStarted) {
        ANS_DBG("ANSAWS", "Acquire FAIL: handle=%p is being destroyed (destructionStarted=true)", (void*)h);
        return nullptr;
    }
    it->second.refcount++;
    ANS_DBG("ANSAWS", "Acquire OK:   handle=%p refcount=%d", (void*)h, it->second.refcount);
    return h;
}

static bool ReleaseAWSHandleRef(ANSCENTER::ANSAWSS3* h) {
    std::lock_guard<std::mutex> lk(AWSHandleRegistryMutex());
    auto it = AWSHandleRegistry().find(h);
    if (it == AWSHandleRegistry().end()) return false;
    it->second.refcount--;
    if (it->second.refcount <= 0) {
        AWSHandleRegistryCV().notify_all();
    }
    return false;  // Only Unregister deletes. Ref drop just signals the CV.
}

static bool UnregisterAWSHandle(ANSCENTER::ANSAWSS3* h) {
    std::unique_lock<std::mutex> lk(AWSHandleRegistryMutex());
    auto it = AWSHandleRegistry().find(h);
    if (it == AWSHandleRegistry().end()) {
        ANS_DBG("ANSAWS", "Unregister: handle=%p NOT in registry (already gone)", (void*)h);
        return false;
    }
    if (it->second.destructionStarted) {
        ANS_DBG("ANSAWS", "Unregister: handle=%p already being destroyed by another thread, returning false", (void*)h);
        return false;
    }
    ANS_DBG("ANSAWS", "Unregister: handle=%p starting (refcount before=%d)", (void*)h, it->second.refcount);
    it->second.destructionStarted = true;
    it->second.refcount--;
    bool ok = AWSHandleRegistryCV().wait_for(lk, std::chrono::seconds(120), [&]() {
        auto it2 = AWSHandleRegistry().find(h);
        return it2 == AWSHandleRegistry().end() || it2->second.refcount <= 0;
    });
    if (!ok) {
        OutputDebugStringA("WARNING: UnregisterAWSHandle timed out waiting for in-flight operations\n");
    }
    AWSHandleRegistry().erase(h);
    return true;
}

class AWSHandleGuard {
    ANSCENTER::ANSAWSS3* engine;
public:
    explicit AWSHandleGuard(ANSCENTER::ANSAWSS3* e) : engine(e) {}
    ~AWSHandleGuard() { if (engine) ReleaseAWSHandleRef(engine); }
    ANSCENTER::ANSAWSS3* get() const { return engine; }
    explicit operator bool() const { return engine != nullptr; }
    AWSHandleGuard(const AWSHandleGuard&) = delete;
    AWSHandleGuard& operator=(const AWSHandleGuard&) = delete;
};

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

// Pure constructor: every call allocates a brand-new ANSUtilities and writes it
// to *Handle. *Handle(in) is ignored completely -- LabVIEW's CLF Node marshalling
// reuses the same temp buffer per call site, so *Handle(in) often contains
// leftover bytes from the previous Create's output even when the actual LabVIEW
// wire is a different, freshly-allocated instance. Inspecting *Handle(in) for
// "is this live?" detection cannot distinguish that case from a genuine
// double-Create-on-same-wire, so we don't try -- we trust the caller.
//
// Trade-off: if a caller really does call Create twice on the same wire without
// Release, the first handle leaks. That is the caller's bug. The alternative
// (releasing live objects we "see" in the input) destroys legitimate parallel
// instances and is far worse. (Same reasoning as CreateANSAWSHandle.)
extern "C" ANSULT_API int  CreateANSUtilityHandle(ANSCENTER::ANSUtilities** Handle, const char* licenseKey) {
	ANS_DBG("ANSUTIL","Create called: HandlePtr=%p, *Handle(in)=%p (input ignored, always allocates new)",
	       (void*)Handle, Handle ? (void*)*Handle : nullptr);
	if (Handle == nullptr || licenseKey == nullptr) {
		ANS_DBG("ANSUTIL","Create FAIL: Handle or licenseKey is null");
		return 0;
	}
	*Handle = nullptr;
	try {
		*Handle = new ANSCENTER::ANSUtilities();
		if (*Handle == nullptr) {
			ANS_DBG("ANSUTIL","Create FAIL: new returned null");
			return 0;
		}
		ANS_DBG("ANSUTIL","Create: allocated handle=%p (uint=%llu), calling Initialize...",
		       (void*)*Handle, (unsigned long long)(uintptr_t)*Handle);
		if ((*Handle)->Initialize(licenseKey)) {
			RegisterUtilHandle(*Handle);
			ANS_DBG("ANSUTIL","Create OK: handle=%p (uint=%llu)",
			       (void*)*Handle, (unsigned long long)(uintptr_t)*Handle);
			return 1;
		}
		// Initialize failed - clean up to prevent memory leak
		ANS_DBG("ANSUTIL","Create FAIL: Initialize returned false, deleting handle=%p", (void*)*Handle);
		delete *Handle;
		*Handle = nullptr;
		return 0;
	}
	catch (std::exception& e) {
		// Clean up on exception to prevent memory leak
		ANS_DBG("ANSUTIL","Create EXCEPTION (std::exception): %s", e.what());
		if (*Handle != nullptr) {
			delete *Handle;
			*Handle = nullptr;
		}
		return 0;
	}
	catch (...) {
		ANS_DBG("ANSUTIL","Create EXCEPTION (unknown)");
		if (*Handle != nullptr) {
			delete *Handle;
			*Handle = nullptr;
		}
		return 0;
	}

}
static int ReleaseANSUtilityHandle_Impl(ANSCENTER::ANSUtilities** Handle) {
    try {
        if (!Handle || !*Handle) {
            ANS_DBG("ANSUTIL","Release: HandlePtr or *Handle is null, no-op");
            return 1;
        }
        ANSCENTER::ANSUtilities* h = *Handle;
        ANS_DBG("ANSUTIL","Release called: handle=%p (uint=%llu)", (void*)h, (unsigned long long)(uintptr_t)h);
        if (!UnregisterUtilHandle(h)) {
            ANS_DBG("ANSUTIL","Release: Unregister returned false (already gone or being destroyed by another thread), handle=%p", (void*)h);
            *Handle = nullptr;
            return 1;
        }
        delete h;
        *Handle = nullptr;
        ANS_DBG("ANSUTIL","Release OK: handle=%p deleted, registry now has %zu entries",
               (void*)h, UtilHandleRegistry().size());
        return 1;
    }
    catch (...) {
        ANS_DBG("ANSUTIL","Release EXCEPTION (unknown)");
        if (Handle) *Handle = nullptr;
        return 0;
    }
}

extern "C" ANSULT_API int  ReleaseANSUtilityHandle(ANSCENTER::ANSUtilities** Handle) {
    __try {
        return ReleaseANSUtilityHandle_Impl(Handle);
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        ANS_DBG("ANSUTIL","ReleaseANSUtilityHandle: SEH exception caught");
        if (Handle) *Handle = nullptr;
        return 0;
    }
}
extern "C" ANSULT_API int  GetFCMAccessToken(ANSCENTER::ANSUtilities** Handle,const char* privateKey, LStrHandle accessToken) {
	ANS_DBG("ANSUTIL","GetFCMAccessToken: *Handle=%p", (void*)(Handle ? *Handle : nullptr));
	if (Handle == nullptr || *Handle == nullptr || privateKey == nullptr || accessToken == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->GetFirebaseCloudMessageAcccessToken(privateKey);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(accessToken, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*accessToken)->cnt = size;
			memcpy((*accessToken)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  CreateAWSSNSTopic(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, LStrHandle arnTopic) {
	ANS_DBG("ANSUTIL","CreateAWSSNSTopic: *Handle=%p, snsTopicName=%s",
	       (void*)(Handle ? *Handle : nullptr), snsTopicName ? snsTopicName : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || arnTopic == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->CreateAWSSNSTopic(snsTopicName);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(arnTopic, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*arnTopic)->cnt = size;
			memcpy((*arnTopic)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  GetFCMAccessTokenCpp(ANSCENTER::ANSUtilities** Handle, const char* privateKey, std::string& accessToken) {
	ANS_DBG("ANSUTIL","GetFCMAccessTokenCpp: *Handle=%p", (void*)(Handle ? *Handle : nullptr));
	if (Handle == nullptr || *Handle == nullptr || privateKey == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		accessToken = guard.get()->GetFirebaseCloudMessageAcccessToken(privateKey);
		if (accessToken.empty() || accessToken.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;

	}
}
extern "C" ANSULT_API int  CreateAWSSNSTopicCpp(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, std::string& arnTopic) {
	ANS_DBG("ANSUTIL","CreateAWSSNSTopicCpp: *Handle=%p, snsTopicName=%s",
	       (void*)(Handle ? *Handle : nullptr), snsTopicName ? snsTopicName : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		arnTopic = guard.get()->CreateAWSSNSTopic(snsTopicName);
		if (arnTopic.empty() || arnTopic.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  DeleteAWSSNSTopic(ANSCENTER::ANSUtilities** Handle, const char* arnTopic) {
	ANS_DBG("ANSUTIL","DeleteAWSSNSTopic: *Handle=%p, arnTopic=%s",
	       (void*)(Handle ? *Handle : nullptr), arnTopic ? arnTopic : "(null)");
	if (Handle == nullptr || *Handle == nullptr || arnTopic == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteAWSSNSTopic(arnTopic)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SubcribeSMSPhoneNumberAWSSNSTopic(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* phoneNumber, LStrHandle subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeSMSPhoneNumberAWSSNSTopic: *Handle=%p, snsTopicName=%s, phoneNumber=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       phoneNumber ? phoneNumber : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || phoneNumber == nullptr || subscribedARN == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SubcribeSMSPhoneNumber(snsTopicName, phoneNumber);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(subscribedARN, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*subscribedARN)->cnt = size;
			memcpy((*subscribedARN)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}

}
extern "C" ANSULT_API int  SubcribeEmailAddressAWSSNSTopic(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* emailAddress, LStrHandle subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeEmailAddressAWSSNSTopic: *Handle=%p, snsTopicName=%s, emailAddress=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       emailAddress ? emailAddress : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || emailAddress == nullptr || subscribedARN == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SubscribeEmailAddress(snsTopicName, emailAddress);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(subscribedARN, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*subscribedARN)->cnt = size;
			memcpy((*subscribedARN)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SendMessageToAWSSNSTopic(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* subjectContent, const char* messageContent, LStrHandle messageId) {
	ANS_DBG("ANSUTIL","SendMessageToAWSSNSTopic: *Handle=%p, snsTopicName=%s, subject=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       subjectContent ? subjectContent : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || subjectContent == nullptr || messageContent == nullptr || messageId == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SendMessageToTopic(snsTopicName, subjectContent, messageContent);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(messageId, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*messageId)->cnt = size;
			memcpy((*messageId)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SendMessageToPhoneNumber(ANSCENTER::ANSUtilities** Handle, const char* phoneNumber, const char* messageContent, LStrHandle messageId) {
	ANS_DBG("ANSUTIL","SendMessageToPhoneNumber: *Handle=%p, phoneNumber=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       phoneNumber ? phoneNumber : "(null)");
	if (Handle == nullptr || *Handle == nullptr || phoneNumber == nullptr || messageContent == nullptr || messageId == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SendMessageToPhoneNumber(phoneNumber, messageContent);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(messageId, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*messageId)->cnt = size;
			memcpy((*messageId)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SubcribeSMSPhoneNumberAWSSNSTopicCpp(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* phoneNumber, std::string& subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeSMSPhoneNumberAWSSNSTopicCpp: *Handle=%p, snsTopicName=%s, phoneNumber=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       phoneNumber ? phoneNumber : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || phoneNumber == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		subscribedARN = guard.get()->SubcribeSMSPhoneNumber(snsTopicName, phoneNumber);
		if (subscribedARN.empty() || subscribedARN.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SubcribeEmailAddressAWSSNSTopicCpp(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* emailAddress, std::string& subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeEmailAddressAWSSNSTopicCpp: *Handle=%p, snsTopicName=%s, emailAddress=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       emailAddress ? emailAddress : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || emailAddress == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		subscribedARN = guard.get()->SubscribeEmailAddress(snsTopicName, emailAddress);
		if (subscribedARN.empty() || subscribedARN.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SendMessageToAWSSNSTopicCpp(ANSCENTER::ANSUtilities** Handle, const char* snsTopicName, const char* subjectContent, const char* messageContent, std::string& messageId) {
	ANS_DBG("ANSUTIL","SendMessageToAWSSNSTopicCpp: *Handle=%p, snsTopicName=%s, subject=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       snsTopicName ? snsTopicName : "(null)",
	       subjectContent ? subjectContent : "(null)");
	if (Handle == nullptr || *Handle == nullptr || snsTopicName == nullptr || subjectContent == nullptr || messageContent == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		messageId = guard.get()->SendMessageToTopic(snsTopicName, subjectContent, messageContent);
		if (messageId.empty() || messageId.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SendMessageToPhoneNumberCpp(ANSCENTER::ANSUtilities** Handle, const char* phoneNumber, const char* messageContent, std::string& messageId) {
	ANS_DBG("ANSUTIL","SendMessageToPhoneNumberCpp: *Handle=%p, phoneNumber=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       phoneNumber ? phoneNumber : "(null)");
	if (Handle == nullptr || *Handle == nullptr || phoneNumber == nullptr || messageContent == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		messageId = guard.get()->SendMessageToPhoneNumber(phoneNumber, messageContent);
		if (messageId.empty() || messageId.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  ListASWTopics(ANSCENTER::ANSUtilities** Handle, LStrHandle arnTopics) {
	ANS_DBG("ANSUTIL","ListASWTopics: *Handle=%p", (void*)(Handle ? *Handle : nullptr));
	if (Handle == nullptr || *Handle == nullptr || arnTopics == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->ListAWSSNSTopic();
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(arnTopics, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*arnTopics)->cnt = size;
			memcpy((*arnTopics)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  AESEncryption(const char* inputString, const char* inputKey, LStrHandle encryptionMessage) {
	ANS_DBG("ANSUTIL","AESEncryption: inputString len=%zu", inputString ? strlen(inputString) : 0);
	if (inputString == nullptr || inputKey == nullptr || encryptionMessage == nullptr) return 0;
	try {
		std::string st = ANSCENTER::ANSUtilities::AESEncryption(inputString, inputKey);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(encryptionMessage, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*encryptionMessage)->cnt = size;
			memcpy((*encryptionMessage)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}

}
extern "C" ANSULT_API int  MD5HashFile(const char* filePath, LStrHandle decryptionMessage)
{
	ANS_DBG("ANSUTIL","MD5HashFile: filePath=%s", filePath ? path_to_filename(std::string(filePath)).c_str() : "(null)");
	if (filePath == nullptr || decryptionMessage == nullptr) return 0;
	try {
		std::string st = ANSCENTER::ANSUtilities::MD5HashFile(filePath);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(decryptionMessage, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*decryptionMessage)->cnt = size;
			memcpy((*decryptionMessage)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  AESDecryption(const char* encryptedString, const char* inputKey, LStrHandle decryptionMessage) {
	ANS_DBG("ANSUTIL","AESDecryption: encryptedString len=%zu", encryptedString ? strlen(encryptedString) : 0);
	if (encryptedString == nullptr || inputKey == nullptr || decryptionMessage == nullptr) return 0;
	try {
		std::string st = ANSCENTER::ANSUtilities::AESDecryption(encryptedString, inputKey);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(decryptionMessage, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*decryptionMessage)->cnt = size;
			memcpy((*decryptionMessage)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}

}
extern "C" ANSULT_API int  ListASWTopicsCpp(ANSCENTER::ANSUtilities** Handle, std::string& arnTopics) {
	ANS_DBG("ANSUTIL","ListASWTopicsCpp: *Handle=%p", (void*)(Handle ? *Handle : nullptr));
	if (Handle == nullptr || *Handle == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		arnTopics = guard.get()->ListAWSSNSTopic();
		if (arnTopics.empty() || arnTopics.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  AESEncryptionCpp(const char* inputString, const char* inputKey, std::string& encryptedString) {
	ANS_DBG("ANSUTIL","AESEncryptionCpp: inputString len=%zu", inputString ? strlen(inputString) : 0);
	if (inputString == nullptr || inputKey == nullptr) return 0;
	try {
		encryptedString = ANSCENTER::ANSUtilities::AESEncryption(inputString, inputKey);
		if (encryptedString.empty() || encryptedString.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  AESDecryptionCpp(const char* encryptedString, const char* inputKey, std::string& decryptionMessage) {
	ANS_DBG("ANSUTIL","AESDecryptionCpp: encryptedString len=%zu", encryptedString ? strlen(encryptedString) : 0);
	if (encryptedString == nullptr || inputKey == nullptr) return 0;
	try {
		decryptionMessage = ANSCENTER::ANSUtilities::AESDecryption(encryptedString, inputKey);
		if (decryptionMessage.empty() || decryptionMessage.find("Error:") != std::string::npos) {
			return 0;
		}
		else {
			return 1;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  AuthenticateGCS(ANSCENTER::ANSUtilities** Handle, const char* jsonKeyString) {
	ANS_DBG("ANSUTIL","AuthenticateGCS: *Handle=%p, jsonKey len=%zu",
	       (void*)(Handle ? *Handle : nullptr), jsonKeyString ? strlen(jsonKeyString) : 0);
	if (Handle == nullptr || *Handle == nullptr || jsonKeyString == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->AuthenticateGCS(jsonKeyString)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadMatToGCS(ANSCENTER::ANSUtilities** Handle, const char* bucketName, const char* objectName, unsigned char* jpeg_string, int32 bufferLength) {
	ANS_DBG("ANSUTIL","UploadMatToGCS: *Handle=%p, bucket=%s, object=%s, len=%d",
	       (void*)(Handle ? *Handle : nullptr),
	       bucketName ? bucketName : "(null)",
	       objectName ? objectName : "(null)",
	       bufferLength);
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || objectName == nullptr || jpeg_string == nullptr || bufferLength <= 0) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		//cv::Mat image = cv::imdecode(cv::Mat(1, bufferLength, CV_8U, jpeg_string), cv::IMREAD_COLOR);
		//if (image.empty()) return 0;
		//if (guard.get()->UploadMatToGCS(bucketName, objectName, image)) return 1;
		//else return 0;
		if (guard.get()->UploadMatToGCS(bucketName, objectName, jpeg_string, bufferLength)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadImageToGCS(ANSCENTER::ANSUtilities** Handle, const char* bucketName, const char* objectName, cv::Mat image) {
	ANS_DBG("ANSUTIL","UploadImageToGCS: *Handle=%p, bucket=%s, object=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       bucketName ? bucketName : "(null)",
	       objectName ? objectName : "(null)");
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || objectName == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		if (image.empty()) return 0;
		if (guard.get()->UploadMatToGCS(bucketName, objectName, image)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SetupServerProxy(ANSCENTER::ANSUtilities** Handle, const char* hostName, int port, const char* userName, const char* passWord) {
	ANS_DBG("ANSUTIL","SetupServerProxy: *Handle=%p, hostName=%s, port=%d, userName=%s",
	       (void*)(Handle ? *Handle : nullptr),
	       hostName ? hostName : "(null)",
	       port,
	       userName ? userName : "(null)");
	if (Handle == nullptr || *Handle == nullptr || hostName == nullptr || userName == nullptr || passWord == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->SetServerProxy(hostName, port, userName, passWord)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  SendEmail(const char* smtpServer, int port,
									const char* userName, const char* password,
									const char* title,
									const char* bodyHTMLContent,
									const char* bodyTextContent,
									const char* fromEmailSender,
									const char* toEmails,
									const char* ccEmails,
									const char* bccEmails)
{
	ANS_DBG("ANSUTIL","SendEmail: smtpServer=%s, port=%d, userName=%s, fromEmailSender=%s, toEmails=%s",
	       smtpServer ? smtpServer : "(null)", port,
	       userName ? userName : "(null)",
	       fromEmailSender ? fromEmailSender : "(null)",
	       toEmails ? toEmails : "(null)");
	if (smtpServer == nullptr || userName == nullptr || password == nullptr ||
		title == nullptr || fromEmailSender == nullptr) return 0;
	try {
		std::vector<std::string> addToEmails;
		std::vector<std::string> addCCEmails;
		std::vector<std::string> addBCCEmails;
		// convert to vectors of strings from semicolon separated strings
		if (toEmails != nullptr && strlen(toEmails) > 0) {
			std::string s = toEmails;
			size_t pos = 0;
			std::string token;
			while ((pos = s.find(';')) != std::string::npos) {
				token = s.substr(0, pos);
				addToEmails.push_back(token);
				s.erase(0, pos + 1);
			}
			if (!s.empty()) addToEmails.push_back(s);
		}
		if (ccEmails != nullptr && strlen(ccEmails) > 0) {
			std::string s = ccEmails;
			size_t pos = 0;
			std::string token;
			while ((pos = s.find(';')) != std::string::npos) {
				token = s.substr(0, pos);
				addCCEmails.push_back(token);
				s.erase(0, pos + 1);
			}
			if (!s.empty()) addCCEmails.push_back(s);
		}
		if (bccEmails != nullptr && strlen(bccEmails) > 0) {
			std::string s = bccEmails;
			size_t pos = 0;
			std::string token;
			while ((pos = s.find(';')) != std::string::npos) {
				token = s.substr(0, pos);
				addBCCEmails.push_back(token);
				s.erase(0, pos + 1);
			}
			if (!s.empty()) addBCCEmails.push_back(s);
		}
		if (ANSCENTER::ANSUtilities::SendEmail(smtpServer, port, userName, password, title, bodyHTMLContent, bodyTextContent, fromEmailSender,
								addToEmails, addCCEmails, addBCCEmails)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}


}

extern "C" ANSULT_API int  RebootSystem() {
	ANS_DBG("ANSUTIL","RebootSystem called");
	try {
		if (ANSCENTER::ANSUtilities::RestartPC()) return 1;
		else return 0;
	}
	catch (...) {
		return 0;
	}
}

extern "C" ANSULT_API int ANSConvertUTF8ToUTF16LE(const char* utf8Str, LStrHandle result, int includeBOM) {
	ANS_DBG("ANSUTIL","ANSConvertUTF8ToUTF16LE: utf8Str len=%zu, includeBOM=%d",
	       utf8Str ? strlen(utf8Str) : 0, includeBOM);
	try {
		if (!utf8Str || !result) return -1;
		int len = (int)strlen(utf8Str);
		if (len == 0) return 0;
		const char bom[2] = { '\xFF', '\xFE' };

		// Check if input contains \uXXXX escape sequences
		bool hasUnicodeEscapes = false;
		for (int i = 0; i + 1 < len; i++) {
			if (utf8Str[i] == '\\' && utf8Str[i + 1] == 'u') { hasUnicodeEscapes = true; break; }
		}

		if (hasUnicodeEscapes) {
			// Two-pass approach: first decode \uXXXX escapes to UTF-8, then convert to UTF-16LE.
			// This correctly handles mixed input (raw UTF-8 + \uXXXX escapes) by producing
			// clean UTF-8 first, then using MultiByteToWideChar for proper UTF-16LE conversion.
			std::string utf8Decoded;
			utf8Decoded.reserve(len);
			for (int i = 0; i < len; ) {
				if (i + 5 < len && utf8Str[i] == '\\' && utf8Str[i + 1] == 'u') {
					char hex[5] = { utf8Str[i + 2], utf8Str[i + 3], utf8Str[i + 4], utf8Str[i + 5], 0 };
					uint32_t cp = (uint32_t)strtoul(hex, nullptr, 16);
					// Encode codepoint as UTF-8
					if (cp <= 0x7F) {
						utf8Decoded += static_cast<char>(cp);
					} else if (cp <= 0x7FF) {
						utf8Decoded += static_cast<char>(0xC0 | (cp >> 6));
						utf8Decoded += static_cast<char>(0x80 | (cp & 0x3F));
					} else {
						utf8Decoded += static_cast<char>(0xE0 | (cp >> 12));
						utf8Decoded += static_cast<char>(0x80 | ((cp >> 6) & 0x3F));
						utf8Decoded += static_cast<char>(0x80 | (cp & 0x3F));
					}
					i += 6;
				} else {
					utf8Decoded += utf8Str[i];
					i++;
				}
			}
			// Now convert the clean UTF-8 to UTF-16LE
			std::string converted = ANSCENTER::ANSUtilities::ConvertUTF8ToUTF16LE(utf8Decoded);
			if (converted.empty()) return 0;
			int dataSize = static_cast<int>(converted.size());
			int bomSize = includeBOM ? 2 : 0;
			int totalSize = bomSize + dataSize;
			MgErr error = DSSetHandleSize(result, sizeof(int32) + totalSize * sizeof(uChar));
			if (error != noErr) return -2;
			(*result)->cnt = totalSize;
			if (includeBOM) memcpy((*result)->str, bom, 2);
			memcpy((*result)->str + bomSize, converted.data(), dataSize);
			return 1;
		}

		std::string converted = ANSCENTER::ANSUtilities::ConvertUTF8ToUTF16LE(utf8Str);
		if (converted.empty()) return 0;
		int dataSize = static_cast<int>(converted.size());
		int bomSize = includeBOM ? 2 : 0;
		int totalSize = bomSize + dataSize;
		MgErr error = DSSetHandleSize(result, sizeof(int32) + totalSize * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = totalSize;
		if (includeBOM) memcpy((*result)->str, bom, 2);
		memcpy((*result)->str + bomSize, converted.data(), dataSize);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSConvertUTF16LEToUTF8(const unsigned char* utf16leBytes, int byteLen, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF16LEToUTF8: byteLen=%d", byteLen);
	try {
		if (!utf16leBytes || byteLen <= 0 || !result) return -1;
		const unsigned char* data = utf16leBytes;
		int dataLen = byteLen;
		// Strip BOM (FF FE) if present
		if (dataLen >= 2 && data[0] == 0xFF && data[1] == 0xFE) {
			data += 2;
			dataLen -= 2;
		}
		if (dataLen <= 0) return 0;
		bool isUtf16le = (dataLen >= 2 && dataLen % 2 == 0);
		if (isUtf16le) {
			bool isAscii = true;
			for (int i = 1; i < dataLen; i += 2) {
				if (data[i] != 0x00) { isAscii = false; break; }
			}
			if (isAscii) {
				int asciiLen = dataLen / 2;
				MgErr error = DSSetHandleSize(result, sizeof(int32) + asciiLen * sizeof(uChar));
				if (error != noErr) return -2;
				(*result)->cnt = asciiLen;
				for (int i = 0; i < asciiLen; i++) (*result)->str[i] = data[i * 2];
				return 1;
			}
		}
		std::string converted = ANSCENTER::ANSUtilities::ConvertUTF16LEToUTF8(
			reinterpret_cast<const char*>(data), dataLen);
		if (converted.empty()) return 0;
		int size = static_cast<int>(converted.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, converted.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSDecodeJsonUnicodeToUTF16LE(const char* escapedStr, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSDecodeJsonUnicodeToUTF16LE: escapedStr len=%zu", escapedStr ? strlen(escapedStr) : 0);
	try {
		if (!escapedStr || !result) return -1;
		std::string decoded = ANSCENTER::ANSUtilities::DecodeJsonUnicodeToUTF16LE(escapedStr);
		if (decoded.empty()) return 0;
		int size = static_cast<int>(decoded.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, decoded.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSConvertUTF16LEToUnicodeEscapes(const unsigned char* utf16leBytes, int byteLen, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF16LEToUnicodeEscapes: byteLen=%d", byteLen);
	try {
		if (!utf16leBytes || byteLen <= 0 || !result) return -1;
		std::string escaped = ANSCENTER::ANSUtilities::ConvertUTF16LEToUnicodeEscapes(
			reinterpret_cast<const char*>(utf16leBytes), byteLen);
		if (escaped.empty()) return 0;
		int size = static_cast<int>(escaped.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, escaped.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

// Helper: copy a std::string into a LabVIEW LStrHandle.
static int CopyStringToLStrHandle(LStrHandle handle, const std::string& str) {
	if (str.empty()) return 0;
	int size = static_cast<int>(str.size());
	MgErr error = DSSetHandleSize(handle, sizeof(int32) + size * sizeof(uChar));
	if (error != noErr) return -2;
	(*handle)->cnt = size;
	memcpy((*handle)->str, str.data(), size);
	return 1;
}

// Helper: copy raw bytes into a LabVIEW LStrHandle.
static int CopyBytesToLStrHandle(LStrHandle handle, const unsigned char* data, int len) {
	if (!data || len <= 0) return 0;
	MgErr error = DSSetHandleSize(handle, sizeof(int32) + len * sizeof(uChar));
	if (error != noErr) return -2;
	(*handle)->cnt = len;
	memcpy((*handle)->str, data, len);
	return 1;
}

// Helper: detect if LabVIEW LStrHandle contains UTF-16LE (BOM or 0x00 bytes).
static bool DetectUTF16LE(const unsigned char* data, int byteLen) {
	if (byteLen >= 2 && data[0] == 0xFF && data[1] == 0xFE) return true;
	for (int i = 0; i < byteLen; i++) {
		if (data[i] == 0x00) return true;
	}
	return false;
}

// Helper: strip BOM from UTF-16LE data. Returns pointer and adjusts length.
static const unsigned char* StripBOM(const unsigned char* data, int& len) {
	if (len >= 2 && data[0] == 0xFF && data[1] == 0xFE) { data += 2; len -= 2; }
	return data;
}

// LStrHandle-safe version: reads raw bytes from LabVIEW LStrHandle directly.
// Two paths:
//   1. Pure UTF-8 (no BOM, no 0x00 bytes, valid UTF-8) → pass through to output as-is
//   2. Contains UTF-16LE (BOM or 0x00 bytes) → RepairLabVIEWUTF16LE (normalizes
//      mixed UTF-8/UTF-16LE + lone spaces to clean UTF-16LE) → convert to UTF-8
extern "C" ANSULT_API int ANSConvertUTF16LEToUTF8_LV(LStrHandle input, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF16LEToUTF8_LV: input=%p, result=%p", (void*)input, (void*)result);
	try {
		if (!input || !result) return -1;
		int byteLen = (*input)->cnt;
		if (byteLen <= 0) return 0;

		// Copy input data first — input and result may be the same LStrHandle
		std::vector<unsigned char> inputCopy(byteLen);
		memcpy(inputCopy.data(), (*input)->str, byteLen);
		const unsigned char* data = inputCopy.data();

		if (DetectUTF16LE(data, byteLen)) {
			// Path 2: UTF-16LE detected — repair mixed encoding, then convert to UTF-8
			int convLen = byteLen;
			const unsigned char* convData = StripBOM(data, convLen);
			if (convLen <= 0) return 0;

			auto repaired = ANSCENTER::ANSUtilities::RepairLabVIEWUTF16LE(convData, convLen);
			std::string converted = ANSCENTER::ANSUtilities::ConvertUTF16LEToUTF8(
				reinterpret_cast<const char*>(repaired.data()), static_cast<int>(repaired.size()));
			return CopyStringToLStrHandle(result, converted);
		}

		if (ANSCENTER::ANSUtilities::IsValidUTF8(data, byteLen)) {
			// Path 1: Pure UTF-8 — pass through as-is
			return CopyBytesToLStrHandle(result, data, byteLen);
		}

		// Fallback: not UTF-16LE, not valid UTF-8 — assume system codepage
#ifdef _WIN32
		int wideLen = MultiByteToWideChar(CP_ACP, 0,
			reinterpret_cast<const char*>(data), byteLen, nullptr, 0);
		if (wideLen > 0) {
			std::wstring wideStr(wideLen, 0);
			MultiByteToWideChar(CP_ACP, 0,
				reinterpret_cast<const char*>(data), byteLen, &wideStr[0], wideLen);
			int utf8Len = WideCharToMultiByte(CP_UTF8, 0,
				wideStr.c_str(), wideLen, nullptr, 0, nullptr, nullptr);
			if (utf8Len > 0) {
				std::string utf8Str(utf8Len, 0);
				WideCharToMultiByte(CP_UTF8, 0,
					wideStr.c_str(), wideLen, &utf8Str[0], utf8Len, nullptr, nullptr);
				return CopyStringToLStrHandle(result, utf8Str);
			}
		}
#endif
		return CopyBytesToLStrHandle(result, data, byteLen);
	}
	catch (...) { return -1; }
}

// LStrHandle-safe version with auto-detection.
// Two paths:
//   1. Pure UTF-8 → convert UTF-8 to Unicode escapes (\uXXXX)
//   2. Contains UTF-16LE → RepairLabVIEWUTF16LE → convert to Unicode escapes
extern "C" ANSULT_API int ANSConvertUTF16LEToUnicodeEscapes_LV(LStrHandle input, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF16LEToUnicodeEscapes_LV: input=%p, result=%p", (void*)input, (void*)result);
	try {
		if (!input || !result) return -1;
		int byteLen = (*input)->cnt;
		if (byteLen <= 0) return 0;

		// Copy input data first — input and result may be the same LStrHandle
		std::vector<unsigned char> inputCopy(byteLen);
		memcpy(inputCopy.data(), (*input)->str, byteLen);
		const unsigned char* data = inputCopy.data();

		std::string escaped;

		if (DetectUTF16LE(data, byteLen)) {
			// Path 2: UTF-16LE detected — repair mixed encoding, then convert to escapes
			int convLen = byteLen;
			const unsigned char* convData = StripBOM(data, convLen);
			if (convLen <= 0) return 0;

			auto repaired = ANSCENTER::ANSUtilities::RepairLabVIEWUTF16LE(convData, convLen);

			// Re-add BOM for ConvertUTF16LEToUnicodeEscapes (it expects optional BOM)
			std::vector<unsigned char> withBom;
			withBom.reserve(2 + repaired.size());
			withBom.push_back(0xFF);
			withBom.push_back(0xFE);
			withBom.insert(withBom.end(), repaired.begin(), repaired.end());

			escaped = ANSCENTER::ANSUtilities::ConvertUTF16LEToUnicodeEscapes(
				reinterpret_cast<const char*>(withBom.data()), static_cast<int>(withBom.size()));
		}
		else {
			// Path 1: No UTF-16LE — get UTF-8, then convert to Unicode escapes
			std::string utf8Str;
			if (ANSCENTER::ANSUtilities::IsValidUTF8(data, byteLen)) {
				utf8Str.assign(reinterpret_cast<const char*>(data), byteLen);
			}
#ifdef _WIN32
			else {
				int wideLen = MultiByteToWideChar(CP_ACP, 0,
					reinterpret_cast<const char*>(data), byteLen, nullptr, 0);
				if (wideLen > 0) {
					std::wstring wideStr(wideLen, 0);
					MultiByteToWideChar(CP_ACP, 0,
						reinterpret_cast<const char*>(data), byteLen, &wideStr[0], wideLen);
					int utf8Len = WideCharToMultiByte(CP_UTF8, 0,
						wideStr.c_str(), wideLen, nullptr, 0, nullptr, nullptr);
					if (utf8Len > 0) {
						utf8Str.resize(utf8Len);
						WideCharToMultiByte(CP_UTF8, 0,
							wideStr.c_str(), wideLen, &utf8Str[0], utf8Len, nullptr, nullptr);
					}
				}
			}
#endif
			if (utf8Str.empty()) {
				utf8Str.assign(reinterpret_cast<const char*>(data), byteLen);
			}
			escaped = ANSCENTER::ANSUtilities::ConvertUTF8ToUnicodeEscapes(utf8Str);
		}

		return CopyStringToLStrHandle(result, escaped);
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSConvertUnicodeEscapesToUTF8(const char* escapedStr, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUnicodeEscapesToUTF8: escapedStr len=%zu", escapedStr ? strlen(escapedStr) : 0);
	try {
		if (!escapedStr || !result) return -1;
		int len = (int)strlen(escapedStr);
		if (len == 0) return 0;
		std::string utf8 = ANSCENTER::ANSUtilities::ConvertUnicodeEscapesToUTF8(escapedStr);
		if (utf8.empty()) return 0;
		int size = static_cast<int>(utf8.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, utf8.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSConvertUTF8ToUnicodeEscapes(const char* utf8Str, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF8ToUnicodeEscapes: utf8Str len=%zu", utf8Str ? strlen(utf8Str) : 0);
	try {
		if (!utf8Str || !result) return -1;
		int len = (int)strlen(utf8Str);
		if (len == 0) return 0;
		std::string escaped = ANSCENTER::ANSUtilities::ConvertUTF8ToUnicodeEscapes(utf8Str);
		if (escaped.empty()) return 0;
		int size = static_cast<int>(escaped.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, escaped.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSDoubleEscapeUnicode(const char* str, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSDoubleEscapeUnicode: str len=%zu", str ? strlen(str) : 0);
	try {
		if (!str || !result) return -1;
		int len = (int)strlen(str);
		if (len == 0) return 0;
		std::string escaped = ANSCENTER::ANSUtilities::DoubleEscapeUnicode(str);
		if (escaped.empty()) return 0;
		int size = static_cast<int>(escaped.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, escaped.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSConvertUTF8ToDoubleEscapedUnicode(const char* utf8Str, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSConvertUTF8ToDoubleEscapedUnicode: utf8Str len=%zu", utf8Str ? strlen(utf8Str) : 0);
	try {
		if (!utf8Str || !result) return -1;
		int len = (int)strlen(utf8Str);
		if (len == 0) return 0;
		std::string escaped = ANSCENTER::ANSUtilities::ConvertUTF8ToDoubleEscapedUnicode(utf8Str);
		if (escaped.empty()) return 0;
		int size = static_cast<int>(escaped.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, escaped.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

extern "C" ANSULT_API int ANSUnescapeDoubleEscapedUnicode(const char* str, LStrHandle result) {
	ANS_DBG("ANSUTIL","ANSUnescapeDoubleEscapedUnicode: str len=%zu", str ? strlen(str) : 0);
	try {
		if (!str || !result) return -1;
		int len = (int)strlen(str);
		if (len == 0) return 0;
		std::string unescaped = ANSCENTER::ANSUtilities::UnescapeDoubleEscapedUnicode(str);
		if (unescaped.empty()) return 0;
		int size = static_cast<int>(unescaped.size());
		MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
		if (error != noErr) return -2;
		(*result)->cnt = size;
		memcpy((*result)->str, unescaped.data(), size);
		return 1;
	}
	catch (...) { return -1; }
}

// AWSS3
//
// Pure constructor: every call allocates a brand-new ANSAWSS3 and writes it to
// *Handle. *Handle(in) is ignored completely -- LabVIEW's CLF Node marshalling
// reuses the same temp buffer per call site, so *Handle(in) often contains
// leftover bytes from the previous Create's output even when the actual LabVIEW
// wire is a different, freshly-allocated instance. Inspecting *Handle(in) for
// "is this live?" detection cannot distinguish that case from a genuine
// double-Create-on-same-wire, so we don't try -- we trust the caller.
//
// Trade-off: if a caller really does call Create twice on the same wire without
// Release, the first handle leaks. That is the caller's bug. The alternative
// (releasing live objects we "see" in the input) destroys legitimate parallel
// instances and is far worse.
//
// Return codes:
//   1  : success, *Handle now points to a new registered instance
//   0  : invalid arg, alloc failure, or Initialize() failed
extern "C" ANSULT_API int  CreateANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* licenseKey) {
	ANS_DBG("ANSAWS", "Create called: HandlePtr=%p, *Handle(in)=%p (input ignored, always allocates new)",
	       (void*)Handle, Handle ? (void*)*Handle : nullptr);
	if (Handle == nullptr || licenseKey == nullptr) return 0;
	*Handle = nullptr;

	try {
		*Handle = new ANSCENTER::ANSAWSS3();
		if (*Handle == nullptr) return 0;
		if ((*Handle)->Initialize(licenseKey)) {
			RegisterAWSHandle(*Handle);
			ANS_DBG("ANSAWS", "Create OK: *Handle(out)=%p (uint=%llu) -- LabVIEW will see this number",
			       (void*)*Handle, (unsigned long long)(uintptr_t)*Handle);
			return 1;
		}
		// Initialize failed - clean up to prevent memory leak
		delete *Handle;
		*Handle = nullptr;
		return 0;
	}
	catch (std::exception& e) {
		// Clean up on exception to prevent memory leak
		if (*Handle != nullptr) {
			delete *Handle;
			*Handle = nullptr;
		}
		return 0;
	}
	catch (...) {
		if (*Handle != nullptr) {
			delete *Handle;
			*Handle = nullptr;
		}
		return 0;
	}
}
static int ReleaseANSAWSHandle_Impl(ANSCENTER::ANSAWSS3** Handle) {
    try {
        if (!Handle || !*Handle) {
            ANS_DBG("ANSAWS", "Release: noop (Handle or *Handle was null)");
            return 1;
        }
        ANSCENTER::ANSAWSS3* h = *Handle;
        ANS_DBG("ANSAWS", "Release called: handle=%p (uint=%llu)",
               (void*)h, (unsigned long long)(uintptr_t)h);
        if (!UnregisterAWSHandle(h)) {
            ANS_DBG("ANSAWS", "Release: handle %p not in registry, clearing wire only", (void*)h);
            *Handle = nullptr;
            return 1;
        }
        delete h;
        *Handle = nullptr;
        ANS_DBG("ANSAWS", "Release OK: handle %p deleted, registry now has %zu entries",
               (void*)h, AWSHandleRegistry().size());
        return 1;
    }
    catch (...) {
        ANS_DBG("ANSAWS", "Release EXCEPTION: clearing wire and returning 0");
        if (Handle) *Handle = nullptr;
        return 0;
    }
}

extern "C" ANSULT_API int  ReleaseANSAWSHandle(ANSCENTER::ANSAWSS3** Handle) {
    __try {
        return ReleaseANSAWSHandle_Impl(Handle);
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        ANS_DBG("ANSAWS", "Release SEH EXCEPTION: clearing wire and returning 0");
        if (Handle) *Handle = nullptr;
        return 0;
    }
}
extern "C" ANSULT_API int  ConnectANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* baseDomain, const char* bucketRegion, const char* serviceName, int port, int bTls, int autoReconnect, int* awsPath) {
	ANS_DBG("ANSAWS", "Connect called: *Handle=%p, baseDomain=%s, region=%s, service=%s, port=%d, tls=%d, autoReconnect=%d",
	       Handle ? (void*)*Handle : nullptr,
	       baseDomain ? baseDomain : "(null)",
	       bucketRegion ? bucketRegion : "(null)",
	       serviceName ? serviceName : "(null)",
	       port, bTls, autoReconnect);
	if (Handle == nullptr || *Handle == nullptr || awsPath == nullptr) {
		ANS_DBG("ANSAWS", "Connect: returning 0 (null arg)");
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) {
		ANS_DBG("ANSAWS", "Connect: returning 0 (handle %p not in registry)", (void*)*Handle);
		return 0;
	}
	try {
		bool bTlsBool = (bTls == 1);
		bool autoReconnectBool = (autoReconnect == 1);
		bool awsPathBool = true;
		int result = guard.get()->Connect(baseDomain, bucketRegion, serviceName, port, bTlsBool, autoReconnectBool, awsPathBool);
		*awsPath = awsPathBool ? 1 : 0;
		ANS_DBG("ANSAWS", "Connect result: %d (1=connected, 0=failed, 2=no internet) awsPath=%d", result, *awsPath);
		return result;  // 1 = connected, 0 = failed, 2 = no internet (retrying)
	}
	catch (std::exception& e) {
		ANS_DBG("ANSAWS", "Connect EXCEPTION: %s", e.what());
		return 0;
	}
	catch (...) {
		ANS_DBG("ANSAWS", "Connect EXCEPTION: unknown");
		return 0;
	}
}
extern "C" ANSULT_API int  SetProxyANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* proxyHost, int proxyPort, const char* proxyUsername, const char* proxyPassword) {
	ANS_DBG("ANSAWS", "SetProxy called: *Handle=%p, host=%s, port=%d, user=%s",
	       Handle ? (void*)*Handle : nullptr,
	       proxyHost ? proxyHost : "(null)",
	       proxyPort,
	       proxyUsername ? proxyUsername : "(null)");
	if (Handle == nullptr || *Handle == nullptr) {
		ANS_DBG("ANSAWS", "SetProxy: returning 0 (null arg)");
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) {
		ANS_DBG("ANSAWS", "SetProxy: returning 0 (handle %p not in registry)", (void*)*Handle);
		return 0;
	}
	try {
		if (guard.get()->SetServerProxy(proxyHost, proxyPort, proxyUsername, proxyPassword)) {
			ANS_DBG("ANSAWS", "SetProxy OK");
			return 1;
		}
		else {
			ANS_DBG("ANSAWS", "SetProxy FAILED (SetServerProxy returned false)");
			return 0;
		}
	}
	catch (std::exception& e) {
		ANS_DBG("ANSAWS", "SetProxy EXCEPTION: %s", e.what());
		return 0;
	}
	catch (...) {
		ANS_DBG("ANSAWS", "SetProxy EXCEPTION: unknown");
		return 0;
	}
}
extern "C" ANSULT_API int  SetAuthenticationANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* accessKey, const char* secretKey) {
	ANS_DBG("ANSAWS", "SetAuth called: *Handle=%p, accessKey=%.6s... (length-only secretKey=%zu)",
	       Handle ? (void*)*Handle : nullptr,
	       accessKey ? accessKey : "(null)",
	       secretKey ? strlen(secretKey) : 0);
	if (Handle == nullptr || *Handle == nullptr ) {
		ANS_DBG("ANSAWS", "SetAuth: returning 0 (null arg)");
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) {
		ANS_DBG("ANSAWS", "SetAuth: returning 0 (handle %p not in registry)", (void*)*Handle);
		return 0;
	}
	try {
		if (guard.get()->SetAuthentication(accessKey, secretKey)) {
			ANS_DBG("ANSAWS", "SetAuth OK");
			return 1;
		}
		else {
			ANS_DBG("ANSAWS", "SetAuth FAILED (SetAuthentication returned false)");
			return 0;
		}
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}

extern "C" ANSULT_API int  ListBucketANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, std::string& bucketList) {
	try {
		// Validate input parameters
		if (Handle == nullptr || *Handle == nullptr) {
			return 0;
		}
		AWSHandleGuard guard(AcquireAWSHandle(*Handle));
		if (!guard) return 0;

		std::vector<std::string> bucketListVec = guard.get()->ListBuckets();

		// Clear the output string first
		bucketList.clear();

		// Return 0 if no buckets found (or you could return 1 with empty string)
		if (bucketListVec.empty()) {
			return 1; // Changed to 1 - successfully got empty list
		}

		// Build the bucket list as a single string with semicolons
		// Reserve approximate space to avoid multiple reallocations
		size_t estimatedSize = 0;
		for (const auto& bucket : bucketListVec) {
			estimatedSize += bucket.length() + 1; // +1 for semicolon
		}
		bucketList.reserve(estimatedSize);

		// Concatenate bucket names
		for (const auto& bucket : bucketListVec) {
			bucketList += bucket + ";";
		}

		// Optional: Remove trailing semicolon
		if (!bucketList.empty() && bucketList.back() == ';') {
			bucketList.pop_back();
		}

		return 1;
	}
	catch (const std::exception& e) {
		// Optional: Log the error if you have access to logger
		// Could also set bucketList to error message if needed
		bucketList.clear();
		return 0;
	}
	catch (...) {
		bucketList.clear();
		return 0;
	}
}
extern "C" ANSULT_API int  ListBucketObjectsANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, std::string& bucketNameList) {
	try {
		// Validate input parameters
		if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
			return 0;
		}
		AWSHandleGuard guard(AcquireAWSHandle(*Handle));
		if (!guard) return 0;

		std::vector<std::string> bucketObjects = guard.get()->ListBucketObjects(bucketName);
		if (bucketObjects.empty()) {
			return 1; // Successfully got empty list
		}

		// Build the bucket object list as a single string with semicolons
		bucketNameList.clear();
		for (const auto& object : bucketObjects) {
			bucketNameList += object + ";";
		}

		// Optional: Remove trailing semicolon
		if (!bucketNameList.empty() && bucketNameList.back() == ';') {
			bucketNameList.pop_back();
		}

		return 1;
	}
	catch (const std::exception& e) {
		// Optional: Log the error if you have access to logger
		// Could also set bucketNameList to error message if needed
		bucketNameList.clear();
		return 0;
	}
	catch (...) {
		bucketNameList.clear();
		return 0;
	}
}
extern "C" ANSULT_API int  ListBucketObjectsWithPrefixANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, std::string& bucketNameList) {
	try {
		// Validate input parameters
		if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
			return 0;
		}
		AWSHandleGuard guard(AcquireAWSHandle(*Handle));
		if (!guard) return 0;

		std::vector<std::string> bucketObjects = guard.get()->ListBucketObjectsWithPrefix(bucketName, prefix);
		if (bucketObjects.empty()) {
			return 1; // Successfully got empty list
		}

		// Build the bucket object list as a single string with semicolons
		bucketNameList.clear();
		for (const auto& object : bucketObjects) {
			bucketNameList += object + ";";
		}

		// Optional: Remove trailing semicolon
		if (!bucketNameList.empty() && bucketNameList.back() == ';') {
			bucketNameList.pop_back();
		}

		return 1;
	}
	catch (const std::exception& e) {
		// Optional: Log the error if you have access to logger
		// Could also set bucketNameList to error message if needed
		bucketNameList.clear();
		return 0;
	}
	catch (...) {
		bucketNameList.clear();
		return 0;
	}
}
extern "C" ANSULT_API int  GetRegionANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, std::string& region) {
	try {
		// Validate input parameters
		if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
			return 0;
		}
		AWSHandleGuard guard(AcquireAWSHandle(*Handle));
		if (!guard) return 0;

		region = guard.get()->GetBucketRegion(bucketName);
		if (region.empty()) {
			return 1; // Successfully got empty region
		}

		return 1;
	}
	catch (const std::exception& e) {
		// Optional: Log the error if you have access to logger
		// Could also set region to error message if needed
		region.clear();
		return 0;
	}
	catch (...) {
		region.clear();
		return 0;
	}
}

extern "C" ANSULT_API int  ListBucketANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, LStrHandle bucketList) {
	if (Handle == nullptr || *Handle == nullptr) {
		return 0;
	}
	try {
		std::string st;
		ListBucketANSAWSHandle_CPP(Handle, st);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(bucketList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*bucketList)->cnt = size;
			memcpy((*bucketList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;

	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  ListBucketObjectsANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, LStrHandle bucketNameList) {
	if (Handle == nullptr || *Handle == nullptr) {
		return 0;
	}
	try {
		std::string st;
		ListBucketObjectsANSAWSHandle_CPP(Handle, bucketName,st);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(bucketNameList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*bucketNameList)->cnt = size;
			memcpy((*bucketNameList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;

	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  ListBucketObjectsWithPrefixANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, LStrHandle bucketNameList) {
	if (Handle == nullptr || *Handle == nullptr) {
		return 0;
	}
	try {
		std::string st;
		ListBucketObjectsWithPrefixANSAWSHandle_CPP(Handle, bucketName, prefix,st);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(bucketNameList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*bucketNameList)->cnt = size;
			memcpy((*bucketNameList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;

	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}

extern "C" ANSULT_API int  GetRegionANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, LStrHandle region) {
		if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || region == nullptr) {
		return 0;
	}
	try {
		std::string st;
		GetRegionANSAWSHandle_CPP(Handle, bucketName, st);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(region, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr)
		{
			(*region)->cnt = size;
			memcpy((*region)->str, st.c_str(), size);
			return 1;
		}
		else return 0;

	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}

extern "C" ANSULT_API int  CreateBucketANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->CreateBucket(bucketName)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  DeleteBucketANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteBucket(bucketName)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}

}
extern "C" ANSULT_API int  CreateBucketPrefixANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->CreateFolder(bucketName,prefix)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  DeleteBucketPrefixANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteFolder(bucketName, prefix)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  DeleteBucketObjectANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* bucketObject) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteBucketObject(bucketName, bucketObject)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadTextDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* textDataPath, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || textDataPath == nullptr || uploadedFilePath == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadTextData(bucketName, textDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadBinaryDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* binaryDataPath, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || binaryDataPath == nullptr || uploadedFilePath == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadBinaryData(bucketName, binaryDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadFileStreamDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* fileDataPath, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || fileDataPath == nullptr || uploadedFilePath == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadFileStream(bucketName, fileDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadMultiPartDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* fileDataPath, int fileSize, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || fileDataPath == nullptr || uploadedFilePath == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadMultipartData(bucketName, fileDataPath, outPath, fileSize)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  DownloadFileStreamANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* objectName, const char* savedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || objectName == nullptr || savedFilePath == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		if (guard.get()->DownloadFile(bucketName, objectName, savedFilePath)) return 1;
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadJpegImageANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || jpeg_string == nullptr || bufferLength <= 0 || fileName == nullptr) {
		return 0; // Handle error
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return -1; // guard error
	try {
		std::string outPath;
		if (guard.get()->UploadJpegImage(bucketName, jpeg_string, bufferLength, fileName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return -2;// failed upload
	}
	catch (std::exception& e) {
		return -3;//excception
	}
	catch (...) {
		return -4;//exception
	}
}
extern "C" ANSULT_API int  UploadPrefixJpegImageANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, LStrHandle uploadedFilePath) {
	ANS_DBG("ANSAWS", "Upload called: HandlePtr=%p, *Handle=%p (uint=%llu), bucket=%s, prefix=%s, file=%s, len=%d",
	       (void*)Handle,
	       Handle ? (void*)*Handle : nullptr,
	       Handle && *Handle ? (unsigned long long)(uintptr_t)*Handle : 0ULL,
	       bucketName ? bucketName : "(null)",
	       prefix ? prefix : "(null)",
	       fileName ? fileName : "(null)",
	       bufferLength);
	if (Handle == nullptr || *Handle == nullptr ||
		bucketName == nullptr || prefix == nullptr ||
		jpeg_string == nullptr || bufferLength <= 0 ||
		fileName == nullptr)
	{
		ANS_DBG("ANSAWS", "Upload: returning 0 (null/invalid arg)");
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) {
		ANS_DBG("ANSAWS", "Upload: returning -1 (handle %p not in registry)", (void*)*Handle);
		return -1;
	}
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixJpegImage(bucketName, prefix, jpeg_string, bufferLength, fileName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			ANS_DBG("ANSAWS", "Upload OK (1): file=%s -> %s",
			       fileName ? fileName : "(null)", outPath.c_str());
			return 1;
		}
		else {
			ANS_DBG("ANSAWS", "Upload FAILED (-2): file=%s, UploadPrefixJpegImage returned false",
			       fileName ? fileName : "(null)");
			return -2;
		}
	}
	catch (std::exception& e) {
		ANS_DBG("ANSAWS", "Upload EXCEPTION (-3): file=%s, what=%s",
		       fileName ? fileName : "(null)", e.what());
		return -3;
	}
	catch (...) {
		ANS_DBG("ANSAWS", "Upload EXCEPTION (-4): file=%s, unknown exception",
		       fileName ? fileName : "(null)");
		return -4;
	}
}
extern "C" ANSULT_API int  UploadPrefixMultiPartDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, const char* fileDataPath, const char* objectName, int fileSize, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr || fileDataPath == nullptr || fileSize <= 0 ) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixMultipartData(bucketName, prefix, fileDataPath, objectName, outPath, fileSize)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
extern "C" ANSULT_API int  UploadPrefixBinaryDataANSAWSHandle(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, const char* binaryDataPath, const char* objectName, LStrHandle uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr || binaryDataPath == nullptr || objectName == nullptr) {
		return 0;
	}
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixBinaryData(bucketName, prefix, binaryDataPath, objectName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) {
		return 0;
	}
	catch (...) {
		return 0;
	}
}
// ── C++ test APIs (std::string& instead of LStrHandle) ──
extern "C" ANSULT_API int UploadTextDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* textDataPath, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || textDataPath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadTextData(bucketName, textDataPath, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadBinaryDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* binaryDataPath, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || binaryDataPath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadBinaryData(bucketName, binaryDataPath, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadFileStreamDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* fileDataPath, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || fileDataPath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadFileStream(bucketName, fileDataPath, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadMultiPartDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* fileDataPath, int fileSize, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || fileDataPath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadMultipartData(bucketName, fileDataPath, uploadedFilePath, fileSize) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadJpegImageANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || jpeg_string == nullptr || bufferLength <= 0 || fileName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadJpegImage(bucketName, jpeg_string, bufferLength, fileName, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadPrefixBinaryDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, const char* binaryDataPath, const char* objectName, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr || binaryDataPath == nullptr || objectName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadPrefixBinaryData(bucketName, prefix, binaryDataPath, objectName, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadPrefixMultiPartDataANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, const char* fileDataPath, const char* objectName, int fileSize, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr || fileDataPath == nullptr || fileSize <= 0) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadPrefixMultipartData(bucketName, prefix, fileDataPath, objectName, uploadedFilePath, fileSize) ? 1 : 0;
	} catch (...) { return 0; }
}
extern "C" ANSULT_API int UploadPrefixJpegImageANSAWSHandle_CPP(ANSCENTER::ANSAWSS3** Handle, const char* bucketName, const char* prefix, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, std::string& uploadedFilePath) {
	if (Handle == nullptr || *Handle == nullptr || bucketName == nullptr || prefix == nullptr || jpeg_string == nullptr || bufferLength <= 0 || fileName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(*Handle));
	if (!guard) return 0;
	try {
		return guard.get()->UploadPrefixJpegImage(bucketName, prefix, jpeg_string, bufferLength, fileName, uploadedFilePath) ? 1 : 0;
	} catch (...) { return 0; }
}

// ════════════════════════════════════════════════════════════════════════════
// V2 API — handle-by-value for LabVIEW (uint64_t instead of Handle**)
// ════════════════════════════════════════════════════════════════════════════

// ── ANSUtilities V2 ──

extern "C" ANSULT_API int GetFCMAccessToken_V2(uint64_t handleVal, const char* privateKey, LStrHandle accessToken) {
	ANS_DBG("ANSUTIL","GetFCMAccessToken_V2: handleVal=%llu", (unsigned long long)handleVal);
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (privateKey == nullptr || accessToken == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->GetFirebaseCloudMessageAcccessToken(privateKey);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(accessToken, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*accessToken)->cnt = size;
			memcpy((*accessToken)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int CreateAWSSNSTopic_V2(uint64_t handleVal, const char* snsTopicName, LStrHandle arnTopic) {
	ANS_DBG("ANSUTIL","CreateAWSSNSTopic_V2: handleVal=%llu, snsTopicName=%s",
	       (unsigned long long)handleVal, snsTopicName ? snsTopicName : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (snsTopicName == nullptr || arnTopic == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->CreateAWSSNSTopic(snsTopicName);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(arnTopic, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*arnTopic)->cnt = size;
			memcpy((*arnTopic)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int DeleteAWSSNSTopic_V2(uint64_t handleVal, const char* arnTopic) {
	ANS_DBG("ANSUTIL","DeleteAWSSNSTopic_V2: handleVal=%llu, arnTopic=%s",
	       (unsigned long long)handleVal, arnTopic ? arnTopic : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (arnTopic == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteAWSSNSTopic(arnTopic)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int ListASWTopics_V2(uint64_t handleVal, LStrHandle arnTopics) {
	ANS_DBG("ANSUTIL","ListASWTopics_V2: handleVal=%llu", (unsigned long long)handleVal);
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (arnTopics == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->ListAWSSNSTopic();
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(arnTopics, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*arnTopics)->cnt = size;
			memcpy((*arnTopics)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SubcribeSMSPhoneNumberAWSSNSTopic_V2(uint64_t handleVal, const char* snsTopicName, const char* phoneNumber, LStrHandle subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeSMSPhoneNumberAWSSNSTopic_V2: handleVal=%llu, snsTopicName=%s, phoneNumber=%s",
	       (unsigned long long)handleVal,
	       snsTopicName ? snsTopicName : "(null)",
	       phoneNumber ? phoneNumber : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (snsTopicName == nullptr || phoneNumber == nullptr || subscribedARN == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SubcribeSMSPhoneNumber(snsTopicName, phoneNumber);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(subscribedARN, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*subscribedARN)->cnt = size;
			memcpy((*subscribedARN)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SubcribeEmailAddressAWSSNSTopic_V2(uint64_t handleVal, const char* snsTopicName, const char* emailAddress, LStrHandle subscribedARN) {
	ANS_DBG("ANSUTIL","SubcribeEmailAddressAWSSNSTopic_V2: handleVal=%llu, snsTopicName=%s, emailAddress=%s",
	       (unsigned long long)handleVal,
	       snsTopicName ? snsTopicName : "(null)",
	       emailAddress ? emailAddress : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (snsTopicName == nullptr || emailAddress == nullptr || subscribedARN == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SubscribeEmailAddress(snsTopicName, emailAddress);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(subscribedARN, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*subscribedARN)->cnt = size;
			memcpy((*subscribedARN)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SendMessageToAWSSNSTopic_V2(uint64_t handleVal, const char* snsTopicName, const char* subjectContent, const char* messageContent, LStrHandle messageId) {
	ANS_DBG("ANSUTIL","SendMessageToAWSSNSTopic_V2: handleVal=%llu, snsTopicName=%s, subject=%s",
	       (unsigned long long)handleVal,
	       snsTopicName ? snsTopicName : "(null)",
	       subjectContent ? subjectContent : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (snsTopicName == nullptr || subjectContent == nullptr || messageContent == nullptr || messageId == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SendMessageToTopic(snsTopicName, subjectContent, messageContent);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(messageId, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*messageId)->cnt = size;
			memcpy((*messageId)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SendMessageToPhoneNumber_V2(uint64_t handleVal, const char* phoneNumber, const char* messageContent, LStrHandle messageId) {
	ANS_DBG("ANSUTIL","SendMessageToPhoneNumber_V2: handleVal=%llu, phoneNumber=%s",
	       (unsigned long long)handleVal,
	       phoneNumber ? phoneNumber : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (phoneNumber == nullptr || messageContent == nullptr || messageId == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->SendMessageToPhoneNumber(phoneNumber, messageContent);
		if (st.empty()) return 0;
		int size = st.length();
		MgErr error;
		error = DSSetHandleSize(messageId, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*messageId)->cnt = size;
			memcpy((*messageId)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SetupServerProxy_V2(uint64_t handleVal, const char* hostName, int port, const char* userName, const char* passWord) {
	ANS_DBG("ANSUTIL","SetupServerProxy_V2: handleVal=%llu, hostName=%s, port=%d, userName=%s",
	       (unsigned long long)handleVal,
	       hostName ? hostName : "(null)",
	       port,
	       userName ? userName : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (hostName == nullptr || userName == nullptr || passWord == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->SetServerProxy(hostName, port, userName, passWord)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int AuthenticateGCS_V2(uint64_t handleVal, const char* jsonKeyString) {
	ANS_DBG("ANSUTIL","AuthenticateGCS_V2: handleVal=%llu, jsonKey len=%zu",
	       (unsigned long long)handleVal,
	       jsonKeyString ? strlen(jsonKeyString) : 0);
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (jsonKeyString == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->AuthenticateGCS(jsonKeyString)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadMatToGCS_V2(uint64_t handleVal, const char* bucketName, const char* objectName, unsigned char* jpeg_string, int32 bufferLength) {
	ANS_DBG("ANSUTIL","UploadMatToGCS_V2: handleVal=%llu, bucket=%s, object=%s, len=%d",
	       (unsigned long long)handleVal,
	       bucketName ? bucketName : "(null)",
	       objectName ? objectName : "(null)",
	       bufferLength);
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || objectName == nullptr || jpeg_string == nullptr || bufferLength <= 0) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->UploadMatToGCS(bucketName, objectName, jpeg_string, bufferLength)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadImageToGCS_V2(uint64_t handleVal, const char* bucketName, const char* objectName, cv::Mat image) {
	ANS_DBG("ANSUTIL","UploadImageToGCS_V2: handleVal=%llu, bucket=%s, object=%s",
	       (unsigned long long)handleVal,
	       bucketName ? bucketName : "(null)",
	       objectName ? objectName : "(null)");
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSUtilities*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || objectName == nullptr) return 0;
	UtilHandleGuard guard(AcquireUtilHandle(_v2h));
	if (!guard) return 0;
	try {
		if (image.empty()) return 0;
		if (guard.get()->UploadMatToGCS(bucketName, objectName, image)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

// ── ANSAWSS3 V2 ──

extern "C" ANSULT_API int ConnectANSAWSHandle_V2(uint64_t handleVal, const char* baseDomain, const char* bucketRegion, const char* serviceName, int port, int bTls, int autoReconnect, int* awsPath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (awsPath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		bool bTlsBool = (bTls == 1);
		bool autoReconnectBool = (autoReconnect == 1);
		bool awsPathBool = true;
		int result = guard.get()->Connect(baseDomain, bucketRegion, serviceName, port, bTlsBool, autoReconnectBool, awsPathBool);
		*awsPath = awsPathBool ? 1 : 0;
		return result;  // 1 = connected, 0 = failed, 2 = no internet (retrying)
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SetProxyANSAWSHandle_V2(uint64_t handleVal, const char* proxyHost, int proxyPort, const char* proxyUsername, const char* proxyPassword) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->SetServerProxy(proxyHost, proxyPort, proxyUsername, proxyPassword)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int SetAuthenticationANSAWSHandle_V2(uint64_t handleVal, const char* accessKey, const char* secretKey) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->SetAuthentication(accessKey, secretKey)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int ListBucketANSAWSHandle_V2(uint64_t handleVal, LStrHandle bucketList) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketList == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::vector<std::string> bucketListVec = guard.get()->ListBuckets();
		std::string st;
		if (!bucketListVec.empty()) {
			for (const auto& bucket : bucketListVec) {
				st += bucket + ";";
			}
			if (!st.empty() && st.back() == ';') {
				st.pop_back();
			}
		}
		if (st.empty()) return 0;
		int size = (int)st.length();
		MgErr error = DSSetHandleSize(bucketList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*bucketList)->cnt = size;
			memcpy((*bucketList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int ListBucketObjectsANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, LStrHandle bucketNameList) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || bucketNameList == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::vector<std::string> bucketObjects = guard.get()->ListBucketObjects(bucketName);
		std::string st;
		if (!bucketObjects.empty()) {
			for (const auto& object : bucketObjects) {
				st += object + ";";
			}
			if (!st.empty() && st.back() == ';') {
				st.pop_back();
			}
		}
		if (st.empty()) return 0;
		int size = (int)st.length();
		MgErr error = DSSetHandleSize(bucketNameList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*bucketNameList)->cnt = size;
			memcpy((*bucketNameList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int ListBucketObjectsWithPrefixANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix, LStrHandle bucketNameList) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || bucketNameList == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::vector<std::string> bucketObjects = guard.get()->ListBucketObjectsWithPrefix(bucketName, prefix);
		std::string st;
		if (!bucketObjects.empty()) {
			for (const auto& object : bucketObjects) {
				st += object + ";";
			}
			if (!st.empty() && st.back() == ';') {
				st.pop_back();
			}
		}
		if (st.empty()) return 0;
		int size = (int)st.length();
		MgErr error = DSSetHandleSize(bucketNameList, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*bucketNameList)->cnt = size;
			memcpy((*bucketNameList)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int GetRegionANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, LStrHandle region) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || region == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string st = guard.get()->GetBucketRegion(bucketName);
		if (st.empty()) return 0;
		int size = (int)st.length();
		MgErr error = DSSetHandleSize(region, sizeof(int32) + size * sizeof(uChar));
		if (error == noErr) {
			(*region)->cnt = size;
			memcpy((*region)->str, st.c_str(), size);
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int CreateBucketANSAWSHandle_V2(uint64_t handleVal, const char* bucketName) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->CreateBucket(bucketName)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int DeleteBucketANSAWSHandle_V2(uint64_t handleVal, const char* bucketName) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteBucket(bucketName)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int CreateBucketPrefixANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->CreateFolder(bucketName, prefix)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int DeleteBucketPrefixANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || prefix == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteFolder(bucketName, prefix)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int DeleteBucketObjectANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* bucketObject) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->DeleteBucketObject(bucketName, bucketObject)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadTextDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* textDataPath, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || textDataPath == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadTextData(bucketName, textDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadBinaryDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* binaryDataPath, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || binaryDataPath == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadBinaryData(bucketName, binaryDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadFileStreamDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* fileDataPath, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || fileDataPath == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadFileStream(bucketName, fileDataPath, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadMultiPartDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* fileDataPath, int fileSize, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || fileDataPath == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadMultipartData(bucketName, fileDataPath, outPath, fileSize)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadJpegImageANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || jpeg_string == nullptr || bufferLength <= 0 || fileName == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadJpegImage(bucketName, jpeg_string, bufferLength, fileName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadPrefixJpegImageANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix, unsigned char* jpeg_string, int32 bufferLength, const char* fileName, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || prefix == nullptr || jpeg_string == nullptr || bufferLength <= 0 || fileName == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixJpegImage(bucketName, prefix, jpeg_string, bufferLength, fileName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadPrefixMultiPartDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix, const char* fileDataPath, const char* objectName, int fileSize, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || prefix == nullptr || fileDataPath == nullptr || fileSize <= 0 || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixMultipartData(bucketName, prefix, fileDataPath, objectName, outPath, fileSize)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int UploadPrefixBinaryDataANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* prefix, const char* binaryDataPath, const char* objectName, LStrHandle uploadedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || prefix == nullptr || binaryDataPath == nullptr || objectName == nullptr || uploadedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		std::string outPath;
		if (guard.get()->UploadPrefixBinaryData(bucketName, prefix, binaryDataPath, objectName, outPath)) {
			int size = (int)outPath.length();
			MgErr error = DSSetHandleSize(uploadedFilePath, sizeof(int32) + size * sizeof(uChar));
			if (error == noErr) {
				(*uploadedFilePath)->cnt = size;
				memcpy((*uploadedFilePath)->str, outPath.c_str(), size);
			}
			return 1;
		}
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}

extern "C" ANSULT_API int DownloadFileStreamANSAWSHandle_V2(uint64_t handleVal, const char* bucketName, const char* objectName, const char* savedFilePath) {
	auto* _v2h = reinterpret_cast<ANSCENTER::ANSAWSS3*>(handleVal); if (!_v2h) return 0;
	if (bucketName == nullptr || objectName == nullptr || savedFilePath == nullptr) return 0;
	AWSHandleGuard guard(AcquireAWSHandle(_v2h));
	if (!guard) return 0;
	try {
		if (guard.get()->DownloadFile(bucketName, objectName, savedFilePath)) return 1;
		else return 0;
	}
	catch (std::exception& e) { return 0; }
	catch (...) { return 0; }
}
