Skip to content
Open
9 changes: 8 additions & 1 deletion src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,14 @@ cc_binary(
] + select({
"//conditions:default": [],
"//src:windows" : ["main_windows.hpp", "main_windows.cpp",],}),
linkopts = LINKOPTS_ADJUSTED,
linkopts = LINKOPTS_ADJUSTED + select({
"//conditions:default": [],
"//src:windows" : [
"runtimeobject.lib",
"oleaut32.lib",
"ole32.lib",
],
}),
copts = COMMON_STATIC_LIBS_COPTS,
deps = [
"//src:ovms_lib",
Expand Down
50 changes: 50 additions & 0 deletions src/main_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <sstream>
#include <string>
#include <chrono>
#include <cstdlib>
#include <iomanip>
#include <utility>
#include <vector>
Expand All @@ -31,6 +32,14 @@
#include <windows.h>
#include <tchar.h>
#include <errors.h>
#pragma warning(push)
#pragma warning(disable : 28252 28253 6101)
#include <winrt/base.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Management.Deployment.h>
#include <winrt/Windows.Storage.h>
#pragma warning(pop)

#include "main_windows.hpp"
#include "module_names.hpp"
Expand Down Expand Up @@ -107,8 +116,49 @@ inline std::wstring stringToWstring(const std::string& str, UINT codePage = CP_T
return str2;
}

// Short-term patch: look up the Tokenizers package directly by its known package name via
// PackageManager, regardless of whether/how it is declared as a dependency in any manifest.
// This avoids relying on Package::Current().Dependencies() at all.
static bool findInstalledPackageByName(const std::wstring& packageName, std::wstring& outInstalledPath) {
winrt::Windows::Management::Deployment::PackageManager packageManager;
for (const winrt::Windows::ApplicationModel::Package& pkg : packageManager.FindPackagesForUser(L"")) {
if (std::wstring(pkg.Id().Name().c_str()) == packageName) {
outInstalledPath = std::wstring(pkg.InstalledLocation().Path().c_str());
return true;
}
}
return false;
}

static void setOpenvinoTokenizersPathFromMsixDependencies() {
constexpr wchar_t PACKAGE_NAME[] = L"Intel.OpenVINO.Tokenizers.2026.3.0.0";
constexpr wchar_t TOKENIZERS_RELATIVE_PATH[] = L"\\runtime\\bin\\intel64\\Release\\openvino_tokenizers.dll";

try {
std::wstring installedPath;
if (findInstalledPackageByName(PACKAGE_NAME, installedPath)) {
const std::wstring dllPath = installedPath + TOKENIZERS_RELATIVE_PATH;
SetEnvironmentVariableW(L"OPENVINO_TOKENIZERS_PATH_GENAI", dllPath.c_str());
_wputenv_s(L"OPENVINO_TOKENIZERS_PATH_GENAI", dllPath.c_str());
DEBUG_LOG("OPENVINO_TOKENIZERS_PATH_GENAI initialized from installed package lookup: " << wstringToString(dllPath));
return;
}
DEBUG_LOG("Tokenizers MSIX package '" << wstringToString(std::wstring(PACKAGE_NAME)) << "' not found for current user. Keeping default behavior.");
} catch (const winrt::hresult_error& ex) {
// Not all deployments are packaged; keep default behavior when package metadata is unavailable.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Not all deployments are packaged; keep default behavior when package metadata is unavailable.
// Not all deployments are packaged; keep default behavior when package metadata is unavailable.
DEBUG_LOG("Failed to resolve Tokenizers dependency: 0x%08X %S",
e.code().value, e.message().c_str());

std::ostringstream errMsg;
errMsg << "Failed to resolve Tokenizers MSIX dependency. HRESULT: 0x" << std::hex << std::uppercase
<< static_cast<unsigned int>(ex.code().value) << ", message: " << winrt::to_string(ex.message());
DEBUG_LOG(errMsg.str());
}
}

int main_windows(int argc, char** argv) {
DEBUG_LOG("Windows Main - Entry");
// Multi-threaded apartment: OVMS is a server process with no STA/message-loop dependency.
winrt::init_apartment(winrt::apartment_type::multi_threaded);
setOpenvinoTokenizersPathFromMsixDependencies();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
setOpenvinoTokenizersPathFromMsixDependencies();
winrt::init_apartment();
setOpenvinoTokenizersPathFromMsixDependencies();


OvmsWindowsServiceManager::instance().ovmsParams.argc = argc;
OvmsWindowsServiceManager::instance().ovmsParams.argv = argv;
OvmsWindowsServiceManager::logParameters(argc, argv, "OVMS Main Argument");
Expand Down