comparison src/ntproc.c @ 408:501cfd01ee6d r21-2-34

Import from CVS: tag r21-2-34
author cvs
date Mon, 13 Aug 2007 11:18:11 +0200
parents b8cc9ab3f761
children de805c49cfc1
comparison
equal deleted inserted replaced
407:ed6218a7d4d3 408:501cfd01ee6d
456 EH_Fail: 456 EH_Fail:
457 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError());); 457 DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
458 return FALSE; 458 return FALSE;
459 } 459 }
460 460
461 #ifndef __MINGW32__
462 /* Return pointer to section header for section containing the given
463 relative virtual address. */
464 static IMAGE_SECTION_HEADER *
465 rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
466 {
467 PIMAGE_SECTION_HEADER section;
468 int i;
469
470 section = IMAGE_FIRST_SECTION (nt_header);
471
472 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
473 {
474 if (rva >= section->VirtualAddress
475 && rva < section->VirtualAddress + section->SizeOfRawData)
476 return section;
477 section++;
478 }
479 return NULL;
480 }
481 #endif
482
483 void
484 win32_executable_type (const char * filename, int * is_dos_app, int * is_cygnus_app)
485 {
486 file_data executable;
487 char * p;
488
489 /* Default values in case we can't tell for sure. */
490 *is_dos_app = FALSE;
491 *is_cygnus_app = FALSE;
492
493 if (!open_input_file (&executable, filename))
494 return;
495
496 p = strrchr (filename, '.');
497
498 /* We can only identify DOS .com programs from the extension. */
499 if (p && stricmp (p, ".com") == 0)
500 *is_dos_app = TRUE;
501 else if (p && (stricmp (p, ".bat") == 0 ||
502 stricmp (p, ".cmd") == 0))
503 {
504 /* A DOS shell script - it appears that CreateProcess is happy to
505 accept this (somewhat surprisingly); presumably it looks at
506 COMSPEC to determine what executable to actually invoke.
507 Therefore, we have to do the same here as well. */
508 /* Actually, I think it uses the program association for that
509 extension, which is defined in the registry. */
510 p = egetenv ("COMSPEC");
511 if (p)
512 win32_executable_type (p, is_dos_app, is_cygnus_app);
513 }
514 else
515 {
516 /* Look for DOS .exe signature - if found, we must also check that
517 it isn't really a 16- or 32-bit Windows exe, since both formats
518 start with a DOS program stub. Note that 16-bit Windows
519 executables use the OS/2 1.x format. */
520
521 #ifdef __MINGW32__
522 /* mingw32 doesn't have enough headers to detect cygwin
523 apps, just do what we can. */
524 FILHDR * exe_header;
525
526 exe_header = (FILHDR*) executable.file_base;
527 if (exe_header->e_magic != DOSMAGIC)
528 goto unwind;
529
530 if ((char*) exe_header->e_lfanew > (char*) executable.size)
531 {
532 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
533 *is_dos_app = TRUE;
534 }
535 else if (exe_header->nt_signature != NT_SIGNATURE)
536 {
537 *is_dos_app = TRUE;
538 }
539 #else
540 IMAGE_DOS_HEADER * dos_header;
541 IMAGE_NT_HEADERS * nt_header;
542
543 dos_header = (PIMAGE_DOS_HEADER) executable.file_base;
544 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
545 goto unwind;
546
547 nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew);
548
549 if ((char*) nt_header > (char*) dos_header + executable.size)
550 {
551 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */
552 *is_dos_app = TRUE;
553 }
554 else if (nt_header->Signature != IMAGE_NT_SIGNATURE &&
555 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE)
556 {
557 *is_dos_app = TRUE;
558 }
559 else if (nt_header->Signature == IMAGE_NT_SIGNATURE)
560 {
561 /* Look for cygwin.dll in DLL import list. */
562 IMAGE_DATA_DIRECTORY import_dir =
563 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
564 IMAGE_IMPORT_DESCRIPTOR * imports;
565 IMAGE_SECTION_HEADER * section;
566
567 section = rva_to_section (import_dir.VirtualAddress, nt_header);
568 imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress,
569 section, executable);
570
571 for ( ; imports->Name; imports++)
572 {
573 char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable);
574
575 if (strcmp (dllname, "cygwin.dll") == 0)
576 {
577 *is_cygnus_app = TRUE;
578 break;
579 }
580 }
581 }
582 #endif
583 }
584
585 unwind:
586 close_file_data (&executable);
587 }
588
589 int
590 compare_env (const void *strp1, const void *strp2)
591 {
592 const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
593
594 while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
595 {
596 if ((*str1) > (*str2))
597 return 1;
598 else if ((*str1) < (*str2))
599 return -1;
600 str1++, str2++;
601 }
602
603 if (*str1 == '=' && *str2 == '=')
604 return 0;
605 else if (*str1 == '=')
606 return -1;
607 else
608 return 1;
609 }
610
611 void 461 void
612 merge_and_sort_env (char **envp1, char **envp2, char **new_envp) 462 merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
613 { 463 {
614 char **optr, **nptr; 464 char **optr, **nptr;
615 int num; 465 int num;
689 /* Determine whether program is a 16-bit DOS executable, or a Win32 539 /* Determine whether program is a 16-bit DOS executable, or a Win32
690 executable that is implicitly linked to the Cygnus dll (implying it 540 executable that is implicitly linked to the Cygnus dll (implying it
691 was compiled with the Cygnus GNU toolchain and hence relies on 541 was compiled with the Cygnus GNU toolchain and hence relies on
692 cygwin.dll to parse the command line - we use this to decide how to 542 cygwin.dll to parse the command line - we use this to decide how to
693 escape quote chars in command line args that must be quoted). */ 543 escape quote chars in command line args that must be quoted). */
694 win32_executable_type (cmdname, &is_dos_app, &is_cygnus_app); 544 mswindows_executable_type (cmdname, &is_dos_app, &is_cygnus_app);
695 545
696 /* On Windows 95, if cmdname is a DOS app, we invoke a helper 546 /* On Windows 95, if cmdname is a DOS app, we invoke a helper
697 application to start it by specifying the helper app as cmdname, 547 application to start it by specifying the helper app as cmdname,
698 while leaving the real app name as argv[0]. */ 548 while leaving the real app name as argv[0]. */
699 if (is_dos_app) 549 if (is_dos_app)