Changeset 51170 in vbox for trunk/src/VBox/Installer/win/Stub
- Timestamp:
- Apr 30, 2014 8:42:52 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Installer/win/Stub/VBoxStub.cpp
r51129 r51170 21 21 #include <Windows.h> 22 22 #include <commctrl.h> 23 #include <fcntl.h> 24 #include <io.h> 23 25 #include <lmerr.h> 24 26 #include <msiquery.h> … … 56 58 #endif 57 59 60 #ifdef DEBUG 61 /* Use an own console window if run in debug mode. */ 62 # define VBOX_STUB_WITH_OWN_CONSOLE 63 #endif 58 64 59 65 /******************************************************************************* … … 90 96 /** List of temporary files. */ 91 97 static RTLISTANCHOR g_TmpFiles; 98 /** Verbosity flag. */ 99 static int g_iVerbosity = 0; 92 100 93 101 … … 802 810 int vrc = RTR3InitExe(argc, &argv, 0); 803 811 if (RT_FAILURE(vrc)) 812 { 813 /* Close the mutex for this application instance. */ 814 CloseHandle(hMutexAppRunning); 815 hMutexAppRunning = NULL; 804 816 return RTMsgInitFailure(vrc); 817 } 818 819 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501 820 # ifndef VBOX_STUB_WITH_OWN_CONSOLE /* Use an own console window if run in debug mode. */ 821 if (!AllocConsole()) 822 { 823 DWORD dwErr = GetLastError(); 824 ShowError("Unable to allocate console, error = %ld\n", 825 dwErr); 826 827 /* Close the mutex for this application instance. */ 828 CloseHandle(hMutexAppRunning); 829 hMutexAppRunning = NULL; 830 return RTEXITCODE_FAILURE; 831 } 832 # else 833 if (!AttachConsole(ATTACH_PARENT_PROCESS)) 834 { 835 DWORD dwErr = GetLastError(); 836 /* Does the program have a console to attach to? */ 837 if (dwErr != ERROR_INVALID_HANDLE) 838 { 839 ShowError("Unable to attach to console, error = %ld\n", 840 dwErr); 841 842 /* Close the mutex for this application instance. */ 843 CloseHandle(hMutexAppRunning); 844 hMutexAppRunning = NULL; 845 return RTEXITCODE_FAILURE; 846 } 847 } 848 # endif /* DEBUG */ 849 850 long lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); 851 int iConHandleStdOut = _open_osfhandle(lStdHandle, _O_TEXT); 852 FILE *hFileStdOut = _fdopen(iConHandleStdOut, "w"); 853 *stdout = *hFileStdOut; 854 855 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); 856 int iConHandleStdErr = _open_osfhandle(lStdHandle, _O_TEXT); 857 FILE *hFileStdErr = _fdopen(iConHandleStdErr, "w"); 858 *stderr = *hFileStdErr; 859 860 setvbuf( stdout, NULL, _IONBF, 0 ); 861 862 #endif 805 863 806 864 /* … … 815 873 #endif 816 874 char szExtractPath[RTPATH_MAX] = {0}; 817 char szMSIArgs[ 4096]= {0};875 char szMSIArgs[_4K] = {0}; 818 876 819 877 /* Parameter definitions. */ … … 844 902 { "-reinstall", 'f', RTGETOPT_REQ_NOTHING }, 845 903 { "/reinstall", 'f', RTGETOPT_REQ_NOTHING }, 904 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 905 { "-verbose", 'v', RTGETOPT_REQ_NOTHING }, 906 { "/verbose", 'v', RTGETOPT_REQ_NOTHING }, 846 907 { "--version", 'V', RTGETOPT_REQ_NOTHING }, 847 908 { "-version", 'V', RTGETOPT_REQ_NOTHING }, … … 854 915 }; 855 916 917 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 918 856 919 /* Parse the parameters. */ 857 920 int ch; 921 bool fParsingDone = false; 858 922 RTGETOPTUNION ValueUnion; 859 923 RTGETOPTSTATE GetState; 860 924 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); 861 while ((ch = RTGetOpt(&GetState, &ValueUnion))) 925 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) 926 && rcExit == RTEXITCODE_SUCCESS 927 && !fParsingDone) 862 928 { 863 929 switch (ch) … … 870 936 "REINSTALLMODE=vomus REINSTALL=ALL"); 871 937 if (RT_FAILURE(vrc)) 872 r eturnShowError("MSI parameters are too long.");938 rcExit = ShowError("MSI parameters are too long."); 873 939 break; 874 940 … … 886 952 break; 887 953 #endif 888 889 954 case 'l': 890 955 fEnableLogging = true; … … 894 959 vrc = RTStrCopy(szExtractPath, sizeof(szExtractPath), ValueUnion.psz); 895 960 if (RT_FAILURE(vrc)) 896 r eturnShowError("Extraction path is too long.");961 rcExit = ShowError("Extraction path is too long."); 897 962 break; 898 963 … … 903 968 vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz); 904 969 if (RT_FAILURE(vrc)) 905 r eturnShowError("MSI parameters are too long.");970 rcExit = ShowError("MSI parameters are too long."); 906 971 break; 907 972 908 973 case 'V': 909 974 ShowInfo("Version: %d.%d.%d.%d", 910 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 911 return VINF_SUCCESS; 975 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, 976 VBOX_SVN_REV); 977 fParsingDone = true; 978 break; 979 980 case 'v': 981 g_iVerbosity++; 982 break; 912 983 913 984 case 'h': … … 929 1000 VBOX_STUB_TITLE, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV, 930 1001 argv[0], argv[0]); 931 return VINF_SUCCESS; 1002 fParsingDone = true; 1003 break; 1004 1005 case VINF_GETOPT_NOT_OPTION: 1006 /* Are (optional) MSI parameters specified and this is the last 1007 * parameter? Append everything to the MSI parameter list then. */ 1008 if (szMSIArgs[0]) 1009 { 1010 vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), " "); 1011 if (RT_SUCCESS(vrc)) 1012 vrc = RTStrCat(szMSIArgs, sizeof(szMSIArgs), ValueUnion.psz); 1013 if (RT_FAILURE(vrc)) 1014 rcExit = ShowError("MSI parameters are too long."); 1015 continue; 1016 } 1017 /* Fall through is intentional. */ 932 1018 933 1019 default: 934 1020 if (g_fSilent) 935 r eturnRTGetOptPrintError(ch, &ValueUnion);936 if (ch == V INF_GETOPT_NOT_OPTION || ch == VERR_GETOPT_UNKNOWN_OPTION)937 ShowError("Unknown option \"%s\"!\n"938 "Please refer to the command line help by specifying \"/?\"\n"939 "to get more information.", ValueUnion.psz);1021 rcExit = RTGetOptPrintError(ch, &ValueUnion); 1022 if (ch == VERR_GETOPT_UNKNOWN_OPTION) 1023 rcExit = ShowError("Unknown option \"%s\"\n" 1024 "Please refer to the command line help by specifying \"/?\"\n" 1025 "to get more information.", ValueUnion.psz); 940 1026 else 941 ShowError("Parameter parsing error: %Rrc\n" 942 "Please refer to the command line help by specifying \"/?\"\n" 943 "to get more information.", ch); 944 return RTEXITCODE_SYNTAX; 945 946 } 947 } 948 949 /* 950 * Determine the extration path if not given by the user, and gather some 951 * other bits we'll be needing later. 952 */ 953 if (szExtractPath[0] == '\0') 954 { 955 vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath)); 956 if (RT_SUCCESS(vrc)) 957 vrc = RTPathAppend(szExtractPath, sizeof(szExtractPath), "VirtualBox"); 958 if (RT_FAILURE(vrc)) 959 return ShowError("Failed to determin extraction path (%Rrc)", vrc); 960 961 } 962 else 963 { 964 /** @todo should check if there is a .custom subdirectory there or not. */ 965 } 966 RTPathChangeToDosSlashes(szExtractPath, true /* Force conversion. */); /* MSI requirement. */ 1027 rcExit = ShowError("Parameter parsing error: %Rrc\n" 1028 "Please refer to the command line help by specifying \"/?\"\n" 1029 "to get more information.", ch); 1030 break; 1031 } 1032 } 1033 1034 if (rcExit != RTEXITCODE_SUCCESS) 1035 vrc = VERR_PARSE_ERROR; 1036 1037 if ( RT_SUCCESS(vrc) 1038 && g_iVerbosity) 1039 { 1040 RTPrintf("Silent installation : %RTbool\n", g_fSilent); 1041 RTPrintf("Logging enabled : %RTbool\n", fEnableLogging); 1042 RTPrintf("Certificate installation : %RTbool\n", fEnableSilentCert); 1043 RTPrintf("Additional MSI parameters: %s\n", 1044 szMSIArgs[0] ? szMSIArgs : "<None>"); 1045 } 1046 1047 if (RT_SUCCESS(vrc)) 1048 { 1049 /* 1050 * Determine the extration path if not given by the user, and gather some 1051 * other bits we'll be needing later. 1052 */ 1053 if (szExtractPath[0] == '\0') 1054 { 1055 vrc = RTPathTemp(szExtractPath, sizeof(szExtractPath)); 1056 if (RT_SUCCESS(vrc)) 1057 vrc = RTPathAppend(szExtractPath, sizeof(szExtractPath), "VirtualBox"); 1058 if (RT_FAILURE(vrc)) 1059 ShowError("Failed to determine extraction path (%Rrc)", vrc); 1060 1061 } 1062 else 1063 { 1064 /** @todo should check if there is a .custom subdirectory there or not. */ 1065 } 1066 RTPathChangeToDosSlashes(szExtractPath, 1067 true /* Force conversion. */); /* MSI requirement. */ 1068 } 967 1069 968 1070 /* Read our manifest. */ 969 1071 PVBOXSTUBPKGHEADER pHeader; 970 vrc = FindData("MANIFEST", (PVOID *)&pHeader, NULL); 971 if (RT_FAILURE(vrc)) 972 return ShowError("Internal package error: Manifest not found (%Rrc)", vrc); 973 /** @todo If we could, we should validate the header. Only the magic isn't 974 * commonly defined, nor the version number... */ 975 976 RTListInit(&g_TmpFiles); 977 978 /* 979 * Up to this point, we haven't done anything that requires any cleanup. 980 * From here on, we do everything in function so we can counter clean up. 981 */ 982 bool fCreatedExtractDir; 983 RTEXITCODE rcExit = ExtractFiles(pHeader->byCntPkgs, szExtractPath, fExtractOnly, &fCreatedExtractDir); 984 if (rcExit == RTEXITCODE_SUCCESS) 985 { 986 if (fExtractOnly) 987 ShowInfo("Files were extracted to: %s", szExtractPath); 988 else 989 { 990 rcExit = CopyCustomDir(szExtractPath); 1072 if (RT_SUCCESS(vrc)) 1073 { 1074 vrc = FindData("MANIFEST", (PVOID *)&pHeader, NULL); 1075 if (RT_FAILURE(vrc)) 1076 rcExit = ShowError("Internal package error: Manifest not found (%Rrc)", vrc); 1077 } 1078 if (RT_SUCCESS(vrc)) 1079 { 1080 /** @todo If we could, we should validate the header. Only the magic isn't 1081 * commonly defined, nor the version number... */ 1082 1083 RTListInit(&g_TmpFiles); 1084 1085 /* 1086 * Up to this point, we haven't done anything that requires any cleanup. 1087 * From here on, we do everything in function so we can counter clean up. 1088 */ 1089 bool fCreatedExtractDir; 1090 rcExit = ExtractFiles(pHeader->byCntPkgs, szExtractPath, 1091 fExtractOnly, &fCreatedExtractDir); 1092 if (rcExit == RTEXITCODE_SUCCESS) 1093 { 1094 if (fExtractOnly) 1095 ShowInfo("Files were extracted to: %s", szExtractPath); 1096 else 1097 { 1098 rcExit = CopyCustomDir(szExtractPath); 991 1099 #ifdef VBOX_WITH_CODE_SIGNING 992 if (rcExit == RTEXITCODE_SUCCESS && fEnableSilentCert && g_fSilent)993 rcExit = InstallCertificate();1100 if (rcExit == RTEXITCODE_SUCCESS && fEnableSilentCert && g_fSilent) 1101 rcExit = InstallCertificate(); 994 1102 #endif 995 unsigned iPackage = 0; 996 while (iPackage < pHeader->byCntPkgs && rcExit == RTEXITCODE_SUCCESS) 997 { 998 rcExit = ProcessPackage(iPackage, szExtractPath, szMSIArgs, fEnableLogging); 999 iPackage++; 1103 unsigned iPackage = 0; 1104 while ( iPackage < pHeader->byCntPkgs 1105 && rcExit == RTEXITCODE_SUCCESS) 1106 { 1107 rcExit = ProcessPackage(iPackage, szExtractPath, 1108 szMSIArgs, fEnableLogging); 1109 iPackage++; 1110 } 1111 1112 /* Don't fail if cleanup fail. At least for now. */ 1113 CleanUp(pHeader->byCntPkgs, 1114 !fEnableLogging 1115 && fCreatedExtractDir ? szExtractPath : NULL); 1000 1116 } 1001 1002 /* Don't fail if cleanup fail. At least for now. */ 1003 CleanUp(pHeader->byCntPkgs, !fEnableLogging && fCreatedExtractDir ? szExtractPath : NULL); 1004 } 1005 } 1006 1007 /* Free any left behind cleanup records (not strictly needed). */ 1008 PSTUBCLEANUPREC pCur, pNext; 1009 RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry) 1010 { 1011 RTListNodeRemove(&pCur->ListEntry); 1012 RTMemFree(pCur); 1013 } 1117 } 1118 1119 /* Free any left behind cleanup records (not strictly needed). */ 1120 PSTUBCLEANUPREC pCur, pNext; 1121 RTListForEachSafe(&g_TmpFiles, pCur, pNext, STUBCLEANUPREC, ListEntry) 1122 { 1123 RTListNodeRemove(&pCur->ListEntry); 1124 RTMemFree(pCur); 1125 } 1126 } 1127 1128 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501 1129 # ifndef VBOX_STUB_WITH_OWN_CONSOLE 1130 if (iConHandleStdErr) 1131 _close(iConHandleStdErr); 1132 if (hFileStdErr) 1133 fclose(hFileStdErr); 1134 if (iConHandleStdOut) 1135 _close(iConHandleStdOut); 1136 if (hFileStdOut) 1137 fclose(hFileStdOut); 1138 # endif /* VBOX_STUB_WITH_OWN_CONSOLE */ 1139 FreeConsole(); 1140 #endif 1014 1141 1015 1142 /*
Note:
See TracChangeset
for help on using the changeset viewer.