Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: runtime/bin/process_win.cc

Issue 11558012: Use FormatMessageW for Windows error messages to handle internationalized messages correctly. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | runtime/bin/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <process.h> 5 #include <process.h>
6 6
7 #include "bin/builtin.h" 7 #include "bin/builtin.h"
8 #include "bin/process.h" 8 #include "bin/process.h"
9 #include "bin/eventhandler.h" 9 #include "bin/eventhandler.h"
10 #include "bin/log.h" 10 #include "bin/log.h"
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 static void CloseProcessPipes(HANDLE handles1[2], 287 static void CloseProcessPipes(HANDLE handles1[2],
288 HANDLE handles2[2], 288 HANDLE handles2[2],
289 HANDLE handles3[2], 289 HANDLE handles3[2],
290 HANDLE handles4[2]) { 290 HANDLE handles4[2]) {
291 CloseProcessPipe(handles1); 291 CloseProcessPipe(handles1);
292 CloseProcessPipe(handles2); 292 CloseProcessPipe(handles2);
293 CloseProcessPipe(handles3); 293 CloseProcessPipe(handles3);
294 CloseProcessPipe(handles4); 294 CloseProcessPipe(handles4);
295 } 295 }
296 296
297 static int SetOsErrorMessage(char* os_error_message, 297
298 int os_error_message_len) { 298 static int SetOsErrorMessage(char** os_error_message) {
299 int error_code = GetLastError(); 299 int error_code = GetLastError();
300 static const int kMaxMessageLength = 256;
301 wchar_t message[kMaxMessageLength];
300 DWORD message_size = 302 DWORD message_size =
301 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 303 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
302 NULL, 304 NULL,
303 error_code, 305 error_code,
304 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 306 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
305 os_error_message, 307 message,
306 os_error_message_len, 308 kMaxMessageLength,
307 NULL); 309 NULL);
308 if (message_size == 0) { 310 if (message_size == 0) {
309 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 311 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
310 Log::PrintErr("FormatMessage failed %d\n", GetLastError()); 312 Log::PrintErr("FormatMessage failed %d\n", GetLastError());
311 } 313 }
312 snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code); 314 _snwprintf(message, kMaxMessageLength, L"OS Error %d", error_code);
313 } 315 }
314 os_error_message[os_error_message_len - 1] = '\0'; 316 message[kMaxMessageLength - 1] = '\0';
317 *os_error_message = StringUtils::WideToUtf8(message);
315 return error_code; 318 return error_code;
316 } 319 }
317 320
318 321
319 int Process::Start(const char* path, 322 int Process::Start(const char* path,
320 char* arguments[], 323 char* arguments[],
321 intptr_t arguments_length, 324 intptr_t arguments_length,
322 const char* working_directory, 325 const char* working_directory,
323 char* environment[], 326 char* environment[],
324 intptr_t environment_length, 327 intptr_t environment_length,
325 intptr_t* in, 328 intptr_t* in,
326 intptr_t* out, 329 intptr_t* out,
327 intptr_t* err, 330 intptr_t* err,
328 intptr_t* id, 331 intptr_t* id,
329 intptr_t* exit_handler, 332 intptr_t* exit_handler,
330 char* os_error_message, 333 char** os_error_message) {
331 int os_error_message_len) {
332 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 334 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
333 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 335 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
334 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 336 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
335 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 337 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
336 338
337 // Generate unique pipe names for the four named pipes needed. 339 // Generate unique pipe names for the four named pipes needed.
338 char pipe_names[4][80]; 340 char pipe_names[4][80];
339 UUID uuid; 341 UUID uuid;
340 RPC_STATUS status = UuidCreateSequential(&uuid); 342 RPC_STATUS status = UuidCreateSequential(&uuid);
341 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { 343 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
344 SetOsErrorMessage(os_error_message);
342 Log::PrintErr("UuidCreateSequential failed %d\n", status); 345 Log::PrintErr("UuidCreateSequential failed %d\n", status);
343 SetOsErrorMessage(os_error_message, os_error_message_len);
344 return status; 346 return status;
345 } 347 }
346 RPC_CSTR uuid_string; 348 RPC_CSTR uuid_string;
347 status = UuidToString(&uuid, &uuid_string); 349 status = UuidToString(&uuid, &uuid_string);
348 if (status != RPC_S_OK) { 350 if (status != RPC_S_OK) {
351 SetOsErrorMessage(os_error_message);
349 Log::PrintErr("UuidToString failed %d\n", status); 352 Log::PrintErr("UuidToString failed %d\n", status);
350 SetOsErrorMessage(os_error_message, os_error_message_len);
351 return status; 353 return status;
352 } 354 }
353 for (int i = 0; i < 4; i++) { 355 for (int i = 0; i < 4; i++) {
354 static const char* prefix = "\\\\.\\Pipe\\dart"; 356 static const char* prefix = "\\\\.\\Pipe\\dart";
355 snprintf(pipe_names[i], 357 snprintf(pipe_names[i],
356 sizeof(pipe_names[i]), 358 sizeof(pipe_names[i]),
357 "%s_%s_%d", prefix, uuid_string, i + 1); 359 "%s_%s_%d", prefix, uuid_string, i + 1);
358 } 360 }
359 status = RpcStringFree(&uuid_string); 361 status = RpcStringFree(&uuid_string);
360 if (status != RPC_S_OK) { 362 if (status != RPC_S_OK) {
363 SetOsErrorMessage(os_error_message);
361 Log::PrintErr("RpcStringFree failed %d\n", status); 364 Log::PrintErr("RpcStringFree failed %d\n", status);
362 SetOsErrorMessage(os_error_message, os_error_message_len);
363 return status; 365 return status;
364 } 366 }
365 367
366 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) { 368 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
367 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 369 int error_code = SetOsErrorMessage(os_error_message);
368 CloseProcessPipes( 370 CloseProcessPipes(
369 stdin_handles, stdout_handles, stderr_handles, exit_handles); 371 stdin_handles, stdout_handles, stderr_handles, exit_handles);
370 return error_code; 372 return error_code;
371 } 373 }
372 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) { 374 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
373 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 375 int error_code = SetOsErrorMessage(os_error_message);
374 CloseProcessPipes( 376 CloseProcessPipes(
375 stdin_handles, stdout_handles, stderr_handles, exit_handles); 377 stdin_handles, stdout_handles, stderr_handles, exit_handles);
376 return error_code; 378 return error_code;
377 } 379 }
378 if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) { 380 if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
379 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 381 int error_code = SetOsErrorMessage(os_error_message);
380 CloseProcessPipes( 382 CloseProcessPipes(
381 stdin_handles, stdout_handles, stderr_handles, exit_handles); 383 stdin_handles, stdout_handles, stderr_handles, exit_handles);
382 return error_code; 384 return error_code;
383 } 385 }
384 if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) { 386 if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
385 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 387 int error_code = SetOsErrorMessage(os_error_message);
386 CloseProcessPipes( 388 CloseProcessPipes(
387 stdin_handles, stdout_handles, stderr_handles, exit_handles); 389 stdin_handles, stdout_handles, stderr_handles, exit_handles);
388 return error_code; 390 return error_code;
389 } 391 }
390 392
391 // Setup info structures. 393 // Setup info structures.
392 STARTUPINFOEX startup_info; 394 STARTUPINFOEX startup_info;
393 ZeroMemory(&startup_info, sizeof(startup_info)); 395 ZeroMemory(&startup_info, sizeof(startup_info));
394 startup_info.StartupInfo.cb = sizeof(startup_info); 396 startup_info.StartupInfo.cb = sizeof(startup_info);
395 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle]; 397 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle];
396 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle]; 398 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle];
397 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle]; 399 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle];
398 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; 400 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
399 401
400 // Setup the handles to inherit. We only want to inherit the three handles 402 // Setup the handles to inherit. We only want to inherit the three handles
401 // for stdin, stdout and stderr. 403 // for stdin, stdout and stderr.
402 SIZE_T size = 0; 404 SIZE_T size = 0;
403 // The call to determine the size of an attribute list always fails with 405 // The call to determine the size of an attribute list always fails with
404 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. 406 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
405 if (!InitializeProcThreadAttributeList(NULL, 1, 0, &size) && 407 if (!InitializeProcThreadAttributeList(NULL, 1, 0, &size) &&
406 GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 408 GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
407 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 409 int error_code = SetOsErrorMessage(os_error_message);
408 CloseProcessPipes( 410 CloseProcessPipes(
409 stdin_handles, stdout_handles, stderr_handles, exit_handles); 411 stdin_handles, stdout_handles, stderr_handles, exit_handles);
410 return error_code; 412 return error_code;
411 } 413 }
412 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = 414 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list =
413 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size)); 415 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
414 ZeroMemory(attribute_list, size); 416 ZeroMemory(attribute_list, size);
415 if (!InitializeProcThreadAttributeList(attribute_list, 1, 0, &size)) { 417 if (!InitializeProcThreadAttributeList(attribute_list, 1, 0, &size)) {
416 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 418 int error_code = SetOsErrorMessage(os_error_message);
417 CloseProcessPipes( 419 CloseProcessPipes(
418 stdin_handles, stdout_handles, stderr_handles, exit_handles); 420 stdin_handles, stdout_handles, stderr_handles, exit_handles);
419 free(attribute_list); 421 free(attribute_list);
420 return error_code; 422 return error_code;
421 } 423 }
422 static const int kNumInheritedHandles = 3; 424 static const int kNumInheritedHandles = 3;
423 HANDLE inherited_handles[kNumInheritedHandles] = 425 HANDLE inherited_handles[kNumInheritedHandles] =
424 { stdin_handles[kReadHandle], 426 { stdin_handles[kReadHandle],
425 stdout_handles[kWriteHandle], 427 stdout_handles[kWriteHandle],
426 stderr_handles[kWriteHandle] }; 428 stderr_handles[kWriteHandle] };
427 if (!UpdateProcThreadAttribute(attribute_list, 429 if (!UpdateProcThreadAttribute(attribute_list,
428 0, 430 0,
429 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, 431 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
430 inherited_handles, 432 inherited_handles,
431 kNumInheritedHandles * sizeof(HANDLE), 433 kNumInheritedHandles * sizeof(HANDLE),
432 NULL, 434 NULL,
433 NULL)) { 435 NULL)) {
434 DeleteProcThreadAttributeList(attribute_list); 436 DeleteProcThreadAttributeList(attribute_list);
435 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 437 int error_code = SetOsErrorMessage(os_error_message);
436 CloseProcessPipes( 438 CloseProcessPipes(
437 stdin_handles, stdout_handles, stderr_handles, exit_handles); 439 stdin_handles, stdout_handles, stderr_handles, exit_handles);
438 free(attribute_list); 440 free(attribute_list);
439 return error_code; 441 return error_code;
440 } 442 }
441 startup_info.lpAttributeList = attribute_list; 443 startup_info.lpAttributeList = attribute_list;
442 444
443 PROCESS_INFORMATION process_info; 445 PROCESS_INFORMATION process_info;
444 ZeroMemory(&process_info, sizeof(process_info)); 446 ZeroMemory(&process_info, sizeof(process_info));
445 447
446 // Transform input strings to system format. 448 // Transform input strings to system format.
447 path = StringUtils::Utf8ToSystemString(path); 449 path = StringUtils::Utf8ToConsoleString(path);
448 for (int i = 0; i < arguments_length; i++) { 450 for (int i = 0; i < arguments_length; i++) {
449 arguments[i] = StringUtils::Utf8ToSystemString(arguments[i]); 451 arguments[i] = StringUtils::Utf8ToConsoleString(arguments[i]);
450 } 452 }
451 453
452 // Compute command-line length. 454 // Compute command-line length.
453 int command_line_length = strlen(path); 455 int command_line_length = strlen(path);
454 for (int i = 0; i < arguments_length; i++) { 456 for (int i = 0; i < arguments_length; i++) {
455 command_line_length += strlen(arguments[i]); 457 command_line_length += strlen(arguments[i]);
456 } 458 }
457 // Account for null termination and one space per argument. 459 // Account for null termination and one space per argument.
458 command_line_length += arguments_length + 1; 460 command_line_length += arguments_length + 1;
459 static const int kMaxCommandLineLength = 32768; 461 static const int kMaxCommandLineLength = 32768;
460 if (command_line_length > kMaxCommandLineLength) { 462 if (command_line_length > kMaxCommandLineLength) {
461 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 463 int error_code = SetOsErrorMessage(os_error_message);
462 CloseProcessPipes( 464 CloseProcessPipes(
463 stdin_handles, stdout_handles, stderr_handles, exit_handles); 465 stdin_handles, stdout_handles, stderr_handles, exit_handles);
464 free(const_cast<char*>(path)); 466 free(const_cast<char*>(path));
465 for (int i = 0; i < arguments_length; i++) free(arguments[i]); 467 for (int i = 0; i < arguments_length; i++) free(arguments[i]);
466 DeleteProcThreadAttributeList(attribute_list); 468 DeleteProcThreadAttributeList(attribute_list);
467 free(attribute_list); 469 free(attribute_list);
468 return error_code; 470 return error_code;
469 } 471 }
470 472
471 // Put together command-line string. 473 // Put together command-line string.
(...skipping 11 matching lines...) Expand all
483 ASSERT(remaining >= 0); 485 ASSERT(remaining >= 0);
484 } 486 }
485 free(const_cast<char*>(path)); 487 free(const_cast<char*>(path));
486 for (int i = 0; i < arguments_length; i++) free(arguments[i]); 488 for (int i = 0; i < arguments_length; i++) free(arguments[i]);
487 489
488 // Create environment block if an environment is supplied. 490 // Create environment block if an environment is supplied.
489 char* environment_block = NULL; 491 char* environment_block = NULL;
490 if (environment != NULL) { 492 if (environment != NULL) {
491 // Convert environment strings to system strings. 493 // Convert environment strings to system strings.
492 for (intptr_t i = 0; i < environment_length; i++) { 494 for (intptr_t i = 0; i < environment_length; i++) {
493 environment[i] = StringUtils::Utf8ToSystemString(environment[i]); 495 environment[i] = StringUtils::Utf8ToConsoleString(environment[i]);
494 } 496 }
495 497
496 // An environment block is a sequence of zero-terminated strings 498 // An environment block is a sequence of zero-terminated strings
497 // followed by a block-terminating zero char. 499 // followed by a block-terminating zero char.
498 intptr_t block_size = 1; 500 intptr_t block_size = 1;
499 for (intptr_t i = 0; i < environment_length; i++) { 501 for (intptr_t i = 0; i < environment_length; i++) {
500 block_size += strlen(environment[i]) + 1; 502 block_size += strlen(environment[i]) + 1;
501 } 503 }
502 environment_block = new char[block_size]; 504 environment_block = new char[block_size];
503 intptr_t block_index = 0; 505 intptr_t block_index = 0;
504 for (intptr_t i = 0; i < environment_length; i++) { 506 for (intptr_t i = 0; i < environment_length; i++) {
505 intptr_t len = strlen(environment[i]); 507 intptr_t len = strlen(environment[i]);
506 intptr_t result = snprintf(environment_block + block_index, 508 intptr_t result = snprintf(environment_block + block_index,
507 len, 509 len,
508 "%s", 510 "%s",
509 environment[i]); 511 environment[i]);
510 ASSERT(result == len); 512 ASSERT(result == len);
511 block_index += len; 513 block_index += len;
512 environment_block[block_index++] = '\0'; 514 environment_block[block_index++] = '\0';
513 } 515 }
514 // Block-terminating zero char. 516 // Block-terminating zero char.
515 environment_block[block_index++] = '\0'; 517 environment_block[block_index++] = '\0';
516 ASSERT(block_index == block_size); 518 ASSERT(block_index == block_size);
517 for (intptr_t i = 0; i < environment_length; i++) free(environment[i]); 519 for (intptr_t i = 0; i < environment_length; i++) free(environment[i]);
518 } 520 }
519 521
520 if (working_directory != NULL) { 522 if (working_directory != NULL) {
521 working_directory = StringUtils::Utf8ToSystemString(working_directory); 523 working_directory = StringUtils::Utf8ToConsoleString(working_directory);
522 } 524 }
523 525
524 // Create process. 526 // Create process.
525 BOOL result = CreateProcess(NULL, // ApplicationName 527 BOOL result = CreateProcess(NULL, // ApplicationName
526 command_line, 528 command_line,
527 NULL, // ProcessAttributes 529 NULL, // ProcessAttributes
528 NULL, // ThreadAttributes 530 NULL, // ThreadAttributes
529 TRUE, // InheritHandles 531 TRUE, // InheritHandles
530 EXTENDED_STARTUPINFO_PRESENT, 532 EXTENDED_STARTUPINFO_PRESENT,
531 environment_block, 533 environment_block,
532 working_directory, 534 working_directory,
533 reinterpret_cast<STARTUPINFO*>(&startup_info), 535 reinterpret_cast<STARTUPINFO*>(&startup_info),
534 &process_info); 536 &process_info);
535 537
536 // Deallocate command-line and environment block strings. 538 // Deallocate command-line and environment block strings.
537 delete[] command_line; 539 delete[] command_line;
538 delete[] environment_block; 540 delete[] environment_block;
539 if (working_directory != NULL) { 541 if (working_directory != NULL) {
540 free(const_cast<char*>(working_directory)); 542 free(const_cast<char*>(working_directory));
541 } 543 }
542 544
543 DeleteProcThreadAttributeList(attribute_list); 545 DeleteProcThreadAttributeList(attribute_list);
544 free(attribute_list); 546 free(attribute_list);
545 547
546 if (result == 0) { 548 if (result == 0) {
547 int error_code = SetOsErrorMessage(os_error_message, os_error_message_len); 549 int error_code = SetOsErrorMessage(os_error_message);
548 CloseProcessPipes( 550 CloseProcessPipes(
549 stdin_handles, stdout_handles, stderr_handles, exit_handles); 551 stdin_handles, stdout_handles, stderr_handles, exit_handles);
550 return error_code; 552 return error_code;
551 } 553 }
552 554
553 ProcessInfoList::AddProcess(process_info.dwProcessId, 555 ProcessInfoList::AddProcess(process_info.dwProcessId,
554 process_info.hProcess, 556 process_info.hProcess,
555 exit_handles[kWriteHandle]); 557 exit_handles[kWriteHandle]);
556 558
557 // Connect the three std streams. 559 // Connect the three std streams.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 594
593 595
594 void Process::TerminateExitCodeHandler() { 596 void Process::TerminateExitCodeHandler() {
595 // Nothing needs to be done on Windows. 597 // Nothing needs to be done on Windows.
596 } 598 }
597 599
598 600
599 intptr_t Process::CurrentProcessId() { 601 intptr_t Process::CurrentProcessId() {
600 return static_cast<intptr_t>(GetCurrentProcessId()); 602 return static_cast<intptr_t>(GetCurrentProcessId());
601 } 603 }
OLDNEW
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | runtime/bin/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698