@@ -121,32 +121,60 @@ int RestartAsAdministrator(
121121 int argc,
122122 char ** argv)
123123{
124+ // Get the exe path
124125 char exe_path[MAX_PATH] = {};
125126 GetModuleFileNameA (NULL , exe_path, sizeof (exe_path));
126127
127- // Combine arguments into single array
128- char args[1024 ] = {};
129- for (int idx = 0 , i = 1 ; i < argc && (size_t ) idx < sizeof (args); ++i) {
130- if (idx >= sizeof (args)) {
131- fprintf (stderr, " internal error: command line arguments too long.\n " );
132- return false ; // was truncated
128+ // Combine arguments into single char* and add -dont_restart_as_admin to
129+ // prevent an endless loop if the escalation fails.
130+ char * args = nullptr ;
131+ {
132+ static char const * const extra_args = " -dont_restart_as_admin" ;
133+ size_t idx = strlen (extra_args);
134+ size_t len = idx + 1 ;
135+ for (int i = 1 ; i < argc; ++i) {
136+ len += strlen (argv[i]) + 2 + 1 ; // +2 for possible quotes, +1 for space or null
133137 }
134138
135- if (argv[i][0 ] != ' \" ' && strchr (argv[i], ' ' )) {
136- idx += snprintf (args + idx, sizeof (args) - idx, " \" %s\" " , argv[i]);
137- } else {
138- idx += snprintf (args + idx, sizeof (args) - idx, " %s" , argv[i]);
139+ args = new char [len];
140+ memcpy (args, extra_args, idx + 1 );
141+ for (int i = 1 ; i < argc; ++i) {
142+ auto addQuotes = argv[i][0 ] != ' \" ' && strchr (argv[i], ' ' ) != nullptr ;
143+ auto n = strlen (argv[i]);
144+
145+ args[idx] = ' ' ;
146+
147+ if (addQuotes) {
148+ args[idx + 1 ] = ' \" ' ;
149+ memcpy (args + idx + 2 , argv[i], n);
150+ args[idx + n + 2 ] = ' \" ' ;
151+ args[idx + n + 3 ] = ' \0 ' ;
152+ idx += 2 ;
153+ } else {
154+ memcpy (args + idx + 1 , argv[i], n + 1 );
155+ }
156+
157+ idx += n + 1 ;
139158 }
140159 }
141160
161+ // Re-run the process with the runas verb
162+ DWORD code = 2 ;
163+
142164 SHELLEXECUTEINFOA info = {};
143165 info.cbSize = sizeof (info);
144- info.fMask = SEE_MASK_NOCLOSEPROCESS;
166+ info.fMask = SEE_MASK_NOCLOSEPROCESS; // return info.hProcess for explicit wait
145167 info.lpVerb = " runas" ;
146168 info.lpFile = exe_path;
147169 info.lpParameters = args;
148- info.nShow = SW_SHOW;
149- if (!ShellExecuteExA (&info) || info.hProcess == NULL ) {
170+ info.nShow = SW_SHOWDEFAULT;
171+ auto ok = ShellExecuteExA (&info);
172+ delete[] args;
173+ if (ok) {
174+ WaitForSingleObject (info.hProcess , INFINITE);
175+ GetExitCodeProcess (info.hProcess , &code);
176+ CloseHandle (info.hProcess );
177+ } else {
150178 fprintf (stderr, " error: failed to elevate privilege " );
151179 int e = GetLastError ();
152180 switch (e) {
@@ -159,17 +187,8 @@ int RestartAsAdministrator(
159187 case ERROR_SHARING_VIOLATION: fprintf (stderr, " (sharing violation).\n " ); break ;
160188 default : fprintf (stderr, " (%u).\n " , e); break ;
161189 }
162- return 2 ;
163190 }
164191
165- WaitForSingleObject (info.hProcess , INFINITE);
166-
167- DWORD code = 0 ;
168- GetExitCodeProcess (info.hProcess , &code);
169- int e = GetLastError ();
170- (void ) e;
171- CloseHandle (info.hProcess );
172-
173192 return code;
174193}
175194
0 commit comments