Skip to content

Commit b81b60e

Browse files
committed
Add GetCloudProvider API function
This new `GetCloudProvider` function provides the ability to query whether a directory is under a cloud provider sync root for a system like OneDrive and whether that provider is active or inhibited. This could be used to help diagnose user reports where the Lua code can open but not read from files.
1 parent 9b7d3a8 commit b81b60e

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

ui_api.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
** fileSize = searchHandle:GetFileSize()
5353
** modified, date, time = searchHande:GetFileModifiedTime()
5454
**
55+
** provider, version, status = GetCloudProvider(path)
56+
**
5557
** SetWindowTitle("<title>")
5658
** x, y = GetCursorPos()
5759
** SetCursorPos(x, y)
@@ -646,6 +648,96 @@ static int l_searchHandleGetFileModifiedTime(lua_State* L)
646648
return 1;
647649
}
648650

651+
// ===================
652+
// Cloud provider info
653+
// ===================
654+
655+
struct CloudProviderInfo {
656+
std::string name;
657+
std::string version;
658+
uint32_t status;
659+
};
660+
661+
#ifdef _WIN32
662+
#include <Windows.h>
663+
#include <cfapi.h>
664+
665+
static std::string NarrowString(std::wstring_view ws) {
666+
auto cb = WideCharToMultiByte(CP_UTF8, 0, ws.data(), ws.size(), nullptr, 0, nullptr, nullptr);
667+
std::string ret(cb, '\0');
668+
WideCharToMultiByte(CP_UTF8, 0, ws.data(), ws.size(), ret.data(), ret.size(), nullptr, nullptr);
669+
return ret;
670+
}
671+
672+
struct CloudProviderLibrary {
673+
CloudProviderLibrary() {
674+
cldLib = LoadLibraryW(L"cldapi.dll");
675+
if (cldLib != nullptr) {
676+
CfGetSyncRootInfoByPath = (decltype (CfGetSyncRootInfoByPath))GetProcAddress(cldLib, "CfGetSyncRootInfoByPath");
677+
}
678+
}
679+
680+
~CloudProviderLibrary() {
681+
FreeLibrary(cldLib);
682+
}
683+
684+
bool Loaded() const { return cldLib != nullptr; }
685+
686+
CloudProviderLibrary(CloudProviderLibrary const&) = delete;
687+
CloudProviderLibrary& operator = (CloudProviderLibrary const&) = delete;
688+
689+
decltype (&::CfGetSyncRootInfoByPath) CfGetSyncRootInfoByPath;
690+
691+
HMODULE cldLib{};
692+
};
693+
694+
static std::optional<CloudProviderInfo> GetCloudProviderInfo(std::filesystem::path const& path) {
695+
HRESULT hr{ S_OK };
696+
DWORD len{};
697+
static std::vector<char> buf(65536);
698+
static CloudProviderLibrary lib;
699+
if (!lib.Loaded()) {
700+
return {};
701+
}
702+
hr = lib.CfGetSyncRootInfoByPath(path.generic_wstring().c_str(), CF_SYNC_ROOT_INFO_PROVIDER, buf.data(), buf.size(), &len);
703+
if (FAILED(hr) && GetLastError() != ERROR_MORE_DATA) {
704+
return {};
705+
}
706+
auto* syncRootInfo = (CF_SYNC_ROOT_PROVIDER_INFO const*)buf.data();
707+
buf.resize(len);
708+
hr = lib.CfGetSyncRootInfoByPath(path.c_str(), CF_SYNC_ROOT_INFO_PROVIDER, buf.data(), len, &len);
709+
if (FAILED(hr)) {
710+
return {};
711+
}
712+
CloudProviderInfo ret{};
713+
ret.name = NarrowString(syncRootInfo->ProviderName);
714+
ret.version = NarrowString(syncRootInfo->ProviderVersion);
715+
ret.status = syncRootInfo->ProviderStatus;
716+
return ret;
717+
}
718+
#else
719+
static std::optional<CloudProviderInfo> GetCloudProviderInfo(std::filesystem::path const& path) {
720+
return {};
721+
}
722+
#endif
723+
724+
static int l_GetCloudProvider(lua_State* L) {
725+
ui_main_c* ui = GetUIPtr(L);
726+
int n = lua_gettop(L);
727+
ui->LAssert(L, n >= 1, "Usage: GetCloudProvider(path)");
728+
ui->LAssert(L, lua_isstring(L, 1), "GetCloudProvider() argument 1: expected string, got %s", luaL_typename(L, 1));
729+
730+
auto info = GetCloudProviderInfo(lua_tostring(L, 1));
731+
if (info) {
732+
lua_pushstring(L, info->name.c_str());
733+
lua_pushstring(L, info->version.c_str());
734+
lua_pushinteger(L, info->status);
735+
return 3;
736+
}
737+
738+
return 0;
739+
}
740+
649741
// =================
650742
// General Functions
651743
// =================
@@ -1287,6 +1379,7 @@ int ui_main_c::InitAPI(lua_State* L)
12871379
lua_setfield(L, LUA_REGISTRYINDEX, "uisearchhandlemeta");
12881380

12891381
// General function
1382+
ADDFUNC(GetCloudProvider);
12901383
ADDFUNC(SetWindowTitle);
12911384
ADDFUNC(GetCursorPos);
12921385
ADDFUNC(SetCursorPos);

0 commit comments

Comments
 (0)