19
19
20
20
#include < cstdlib>
21
21
#include < cstring>
22
+ // #include <limits> // No longer needed
22
23
#include < string>
23
24
#include < vector>
24
25
@@ -33,46 +34,89 @@ namespace internal {
33
34
// Helper function to retrieve the full path of the current executable.
34
35
// Returns an empty string on failure.
35
36
static 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 ;
38
39
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 ();
57
75
}
58
76
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);
66
94
}
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
+
68
105
} 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 ();
73
113
}
74
114
}
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 ();
76
120
}
77
121
78
122
// Helper function to calculate SHA256 hash of a file.
0 commit comments