1919
2020#include < cstdlib>
2121#include < cstring>
22+ // #include <limits> // No longer needed
2223#include < string>
2324#include < vector>
2425
@@ -33,46 +34,89 @@ namespace internal {
3334// Helper function to retrieve the full path of the current executable.
3435// Returns an empty string on failure.
3536static std::wstring GetExecutablePath () {
36- std::wstring executable_path_str ;
37- wchar_t * wpgmptr_val = nullptr ;
37+ std::vector< wchar_t > buffer ;
38+ const size_t kInitialBufferSize = MAX_PATH + 1 ;
3839
39- // Prefer _get_wpgmptr()
40- errno_t err_w = _get_wpgmptr (&wpgmptr_val);
41- if (err_w == 0 && wpgmptr_val != nullptr && wpgmptr_val[0 ] != L' \0 ' ) {
42- executable_path_str = wpgmptr_val;
43- } else {
44- // Fallback to _get_pgmptr() and convert to wide string
45- char * pgmptr_val = nullptr ;
46- errno_t err_c = _get_pgmptr (&pgmptr_val);
47- if (err_c == 0 && pgmptr_val != nullptr && pgmptr_val[0 ] != ' \0 ' ) {
48- // Convert narrow string to wide string using CP_ACP (system default ANSI
49- // code page)
50- int wide_char_count = MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
51- pgmptr_val, -1 , NULL , 0 );
52- if (wide_char_count == 0 ) { // Failure if count is 0
53- DWORD conversion_error = GetLastError ();
54- LogError (LOG_TAG " Invalid executable path. Error: %u" ,
55- conversion_error);
56- return L" " ;
40+ // First attempt with MAX_PATH + 1
41+ // Note: std::vector::resize can throw std::bad_alloc if allocation fails.
42+ // Per requirements, no try/catch here.
43+ buffer.reserve (kInitialBufferSize );
44+ buffer.resize (kInitialBufferSize );
45+
46+ DWORD length = GetModuleFileNameW (NULL , buffer.data (),
47+ static_cast <DWORD>(buffer.size ()));
48+
49+ if (length == 0 ) {
50+ DWORD error_code = GetLastError ();
51+ LogError (LOG_TAG " GetModuleFileNameW (initial) failed. Error: %u" ,
52+ error_code);
53+ return std::wstring ();
54+ }
55+
56+ if (length < buffer.size ()) {
57+ return std::wstring (buffer.data (), length);
58+ }
59+
60+ // If length == buffer.size(), check if it was due to insufficient buffer.
61+ if (length == buffer.size ()) { // Could also be length >= buffer.size()
62+ DWORD error_code = GetLastError ();
63+ if (error_code == ERROR_INSUFFICIENT_BUFFER) {
64+ // Buffer was too small, try a larger one.
65+ const size_t kMaxExecutablePathSize = 65536 ;
66+
67+ // If initial buffer was already this big or bigger, no point retrying.
68+ if (kInitialBufferSize >= kMaxExecutablePathSize ) {
69+ LogError (
70+ LOG_TAG
71+ " Initial buffer attempt failed due to insufficient size, but "
72+ " initial size (%zu) >= kMaxExecutablePathSize (%zu)." ,
73+ kInitialBufferSize , kMaxExecutablePathSize );
74+ return std::wstring ();
5775 }
5876
59- std::vector<wchar_t > wide_path_buffer (wide_char_count);
60- if (MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, pgmptr_val, -1 ,
61- wide_path_buffer.data (), wide_char_count) == 0 ) {
62- DWORD conversion_error = GetLastError ();
63- LogError (LOG_TAG " Invalid executable path. Error: %u" ,
64- conversion_error);
65- return L" " ;
77+ buffer.clear (); // Optional: clear contents before large resize
78+ // Note: std::vector::resize can throw std::bad_alloc.
79+ buffer.reserve (kMaxExecutablePathSize );
80+ buffer.resize (kMaxExecutablePathSize );
81+
82+ DWORD length_large = GetModuleFileNameW (
83+ NULL , buffer.data (), static_cast <DWORD>(buffer.size ()));
84+
85+ if (length_large == 0 ) {
86+ DWORD error_code_large = GetLastError ();
87+ LogError (LOG_TAG " GetModuleFileNameW (large buffer) failed. Error: %u" ,
88+ error_code_large);
89+ return std::wstring ();
90+ }
91+
92+ if (length_large < buffer.size ()) {
93+ return std::wstring (buffer.data (), length_large);
6694 }
67- executable_path_str = wide_path_buffer.data ();
95+
96+ // If length_large is still equal to or greater than buffer size,
97+ // the path is too long even for the large buffer, or truncated.
98+ LogError (
99+ LOG_TAG
100+ " GetModuleFileNameW (large buffer) result too long or truncated. "
101+ " Length: %u, Buffer Size: %zu" ,
102+ length_large, buffer.size ());
103+ return std::wstring ();
104+
68105 } else {
69- // Both _get_wpgmptr and _get_pgmptr failed or returned empty/null
70- LogError (LOG_TAG " Can't determine executable directory. Errors: %d, %d" ,
71- err_w, err_c);
72- return L" " ;
106+ // length == buffer.size() but not ERROR_INSUFFICIENT_BUFFER.
107+ LogError (
108+ LOG_TAG
109+ " GetModuleFileNameW (initial) returned full buffer but error is not "
110+ " ERROR_INSUFFICIENT_BUFFER. Error: %u" ,
111+ error_code);
112+ return std::wstring ();
73113 }
74114 }
75- return executable_path_str;
115+
116+ // Should not be reached if logic is correct, but as a fallback.
117+ // This case implies length > buffer.size() initially, which is unexpected.
118+ LogError (LOG_TAG " GetModuleFileNameW (initial) unexpected state. Length: %u" , length);
119+ return std::wstring ();
76120}
77121
78122// Helper function to calculate SHA256 hash of a file.
0 commit comments