diff --git a/analytics/generate_windows_stubs.py b/analytics/generate_windows_stubs.py index 4fdd34f7bd..3ecf6a1043 100755 --- a/analytics/generate_windows_stubs.py +++ b/analytics/generate_windows_stubs.py @@ -159,6 +159,7 @@ def generate_function_pointers(dll_file_path, header_file_path, output_h_path, o f.write(f"// Generated from {os.path.basename(header_file_path)} by {os.path.basename(sys.argv[0])}\n\n") f.write(f"#ifndef {header_guard}\n") f.write(f"#define {header_guard}\n\n") + f.write(f"#define ANALYTICS_API // filter out from header copy\n\n") f.write("#include // needed for bool type in pure C\n\n") f.write("// --- Copied from original header ---\n") diff --git a/analytics/src/analytics_desktop.cc b/analytics/src/analytics_desktop.cc index 5fd7da9afd..fca5d9cc4d 100644 --- a/analytics/src/analytics_desktop.cc +++ b/analytics/src/analytics_desktop.cc @@ -28,8 +28,7 @@ #if defined(_WIN32) #include - -#include "analytics/src/analytics_windows.h" +#include "analytics_windows.h" #endif // defined(_WIN32) namespace firebase { @@ -39,6 +38,13 @@ namespace analytics { #define ANALYTICS_DLL_FILENAME L"analytics_win.dll" static HMODULE g_analytics_module = 0; +// It's generally safer to use local std::string copies within Initialize +// for app_id and package_name to ensure their lifetime if Initialize +// could theoretically be called multiple times with different App objects, +// or if AppOptions getters returned temporaries. +// Given AppOptions structure, direct use of app.options().app_id() etc. +// within the Initialize call *should* be safe as App outlives the call, +// but local copies are more robust. #endif // defined(_WIN32) // Future data for analytics. @@ -49,10 +55,7 @@ static int g_fake_instance_id = 0; // Initializes the Analytics desktop API. // This function must be called before any other Analytics methods. void Initialize(const App& app) { - // The 'app' parameter is not directly used by the underlying Google Analytics - // C API for Windows for global initialization. It's included for API - // consistency with other Firebase platforms. - (void)app; + // app parameter is now used to retrieve AppOptions. g_initialized = true; internal::RegisterTerminateOnDefaultAppDestroy(); @@ -62,8 +65,9 @@ void Initialize(const App& app) { #if defined(_WIN32) if (!g_analytics_module) { std::vector allowed_hashes; - for (int i=0; i < FirebaseAnalytics_KnownWindowsDllHashCount; i++) { - allowed_hashes.push_back(std::string(FirebaseAnalytics_KnownWindowsDllHashes[i])); + for (int i = 0; i < FirebaseAnalytics_KnownWindowsDllHashCount; i++) { + allowed_hashes.push_back( + std::string(FirebaseAnalytics_KnownWindowsDllHashes[i])); } g_analytics_module = @@ -71,8 +75,8 @@ void Initialize(const App& app) { ANALYTICS_DLL_FILENAME, allowed_hashes); if (g_analytics_module) { - int num_loaded = FirebaseAnalytics_LoadDynamicFunctions( - g_analytics_module); // Ensure g_analytics_module is used + int num_loaded = + FirebaseAnalytics_LoadDynamicFunctions(g_analytics_module); if (num_loaded < FirebaseAnalytics_DynamicFunctionCount) { LogWarning( "Analytics: Failed to load functions from Google Analytics " @@ -81,12 +85,47 @@ void Initialize(const App& app) { FirebaseAnalytics_UnloadDynamicFunctions(); FreeLibrary(g_analytics_module); g_analytics_module = 0; + // Do not proceed with C API initialization if functions didn't load } else { LogInfo("Analytics: Loaded Google Analytics module."); + + // Initialize Google Analytics C API + std::string current_app_id = app.options().app_id(); + std::string current_package_name = app.options().package_name(); + + GoogleAnalytics_Options* c_options = GoogleAnalytics_Options_Create(); + if (!c_options) { + LogError("Analytics: Failed to create GoogleAnalytics_Options."); + } else { + c_options->app_id = current_app_id.c_str(); + c_options->package_name = current_package_name.c_str(); + c_options->analytics_collection_enabled_at_first_launch = true; + // c_options->reserved is initialized by + // GoogleAnalytics_Options_Create + + LogInfo( + "Analytics: Initializing Google Analytics C API with App ID: %s, " + "Package Name: %s", + c_options->app_id ? c_options->app_id : "null", + c_options->package_name ? c_options->package_name : "null"); + + if (!GoogleAnalytics_Initialize(c_options)) { + LogError("Analytics: Failed to initialize Google Analytics C API."); + // GoogleAnalytics_Initialize destroys c_options automatically if + // created by _Create + } else { + LogInfo( + "Analytics: Google Analytics C API initialized successfully."); + } + } } + } else { + // LogWarning for g_analytics_module load failure is handled by + // VerifyAndLoadAnalyticsLibrary + g_analytics_module = 0; // Ensure it's null if loading failed } } -#endif +#endif // defined(_WIN32) } namespace internal { diff --git a/analytics/src/analytics_desktop_dynamic.h b/analytics/src/analytics_desktop_dynamic.h index 75abbcc53d..55567bd1ba 100644 --- a/analytics/src/analytics_desktop_dynamic.h +++ b/analytics/src/analytics_desktop_dynamic.h @@ -17,6 +17,8 @@ #ifndef FIREBASE_ANALYTICS_SRC_WINDOWS_ANALYTICS_DESKTOP_DYNAMIC_H_ #define FIREBASE_ANALYTICS_SRC_WINDOWS_ANALYTICS_DESKTOP_DYNAMIC_H_ +#define ANALYTICS_API // filter out from header copy + #include // needed for bool type in pure C // --- Copied from original header --- diff --git a/analytics/src/analytics_windows.cc b/analytics/src/analytics_windows.cc index 1e3991e381..5398d8136c 100644 --- a/analytics/src/analytics_windows.cc +++ b/analytics/src/analytics_windows.cc @@ -99,11 +99,12 @@ static std::string CalculateFileSha256(HANDLE hFile) { DWORD dwError = GetLastError(); LogError(LOG_TAG "CalculateFileSha256.SetFilePointer failed. Error: %u", dwError); - return ""; // Return empty string on failure + return ""; // Return empty string on failure } // Acquire Crypto Provider. - // Using CRYPT_VERIFYCONTEXT for operations that don't require private key access. + // Using CRYPT_VERIFYCONTEXT for operations that don't require private key + // access. if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { DWORD dwError = GetLastError(); @@ -152,7 +153,8 @@ static std::string CalculateFileSha256(HANDLE hFile) { // --- Get the binary hash value --- DWORD cbHashValue = 0; DWORD dwCount = sizeof(DWORD); - if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&cbHashValue, &dwCount, 0)) { + if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&cbHashValue, &dwCount, + 0)) { DWORD dwError = GetLastError(); LogError(LOG_TAG "CalculateFileSha256.CryptGetHashParam (HP_HASHSIZE) failed. " @@ -179,12 +181,13 @@ static std::string CalculateFileSha256(HANDLE hFile) { // --- Convert the binary hash to a hex string --- DWORD hex_string_size = 0; if (!CryptBinaryToStringA(binary_hash_value.data(), binary_hash_value.size(), - CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, - NULL, &hex_string_size)) { + CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, NULL, + &hex_string_size)) { DWORD dwError = GetLastError(); - LogError(LOG_TAG - "CalculateFileSha256.CryptBinaryToStringA (size) failed. Error: %u", - dwError); + LogError( + LOG_TAG + "CalculateFileSha256.CryptBinaryToStringA (size) failed. Error: %u", + dwError); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); return ""; @@ -196,7 +199,8 @@ static std::string CalculateFileSha256(HANDLE hFile) { &hex_hash_string[0], &hex_string_size)) { DWORD dwError = GetLastError(); LogError(LOG_TAG - "CalculateFileSha256.CryptBinaryToStringA (conversion) failed. Error: %u", + "CalculateFileSha256.CryptBinaryToStringA (conversion) failed. " + "Error: %u", dwError); CryptDestroyHash(hHash); CryptReleaseContext(hProv, 0); @@ -286,9 +290,9 @@ HMODULE VerifyAndLoadAnalyticsLibrary( if (calculated_hash == expected_hash) { hash_matched = true; break; - } - else { - LogDebug(LOG_TAG "Hash mismatch: got %s expected %s", calculated_hash.c_str(), expected_hash.c_str()); + } else { + LogDebug(LOG_TAG "Hash mismatch: got %s expected %s", + calculated_hash.c_str(), expected_hash.c_str()); } }