Changeset 96571 in vbox for trunk/src/VBox/Installer/win/StubBld
- Timestamp:
- Sep 1, 2022 8:34:00 PM (2 years ago)
- Location:
- trunk/src/VBox/Installer/win/StubBld
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Installer/win/StubBld/VBoxStubBld.cpp
r96407 r96571 39 39 #include "VBoxStubBld.h" 40 40 41 HRESULT GetFile (const char* pszFilePath, 42 HANDLE* phFile, 43 DWORD* pdwFileSize) 44 { 45 HRESULT hr = S_OK; 46 *phFile = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 47 if (INVALID_HANDLE_VALUE == *phFile) 48 hr = HRESULT_FROM_WIN32(GetLastError()); 41 42 static HRESULT GetFile(const char *pszFilePath, HANDLE *phFile, DWORD *pcbFile) 43 { 44 HANDLE hFile = CreateFileA(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, 45 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 46 if (hFile != INVALID_HANDLE_VALUE) 47 { 48 SetLastError(NO_ERROR); 49 LARGE_INTEGER cbFile; 50 if (GetFileSizeEx(hFile, &cbFile)) 51 { 52 if (cbFile.HighPart == 0) 53 { 54 *pcbFile = cbFile.LowPart; 55 *phFile = hFile; 56 return S_OK; 57 } 58 fprintf(stderr, "error: File '%s' is too large: %llu bytes\n", pszFilePath, cbFile.QuadPart); 59 } 60 else 61 fprintf(stderr, "error: GetFileSizeEx failed on '%s': %lu\n", pszFilePath, GetLastError()); 62 CloseHandle(hFile); 63 } 49 64 else 50 { 51 *pdwFileSize = ::GetFileSize(*phFile, NULL); 52 if (!*pdwFileSize) 53 hr = HRESULT_FROM_WIN32(GetLastError()); 54 } 55 return hr; 56 } 57 58 HRESULT UpdateResource(HANDLE hFile, 59 DWORD dwFileSize, 60 HANDLE hResourceUpdate, 61 const char *pszResourceType, 62 const char *pszResourceId) 63 { 64 HRESULT hr = S_OK; 65 66 HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 67 PVOID pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, dwFileSize); 68 if (!UpdateResourceA(hResourceUpdate, pszResourceType, pszResourceId, 69 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pvFile, dwFileSize)) 70 hr = HRESULT_FROM_WIN32(GetLastError()); 71 72 if (pvFile) 73 UnmapViewOfFile(pvFile); 74 75 if (hMap) 65 fprintf(stderr, "error: CreateFileA failed on '%s': %lu\n", pszFilePath, GetLastError()); 66 *phFile = INVALID_HANDLE_VALUE; 67 return E_FAIL; 68 } 69 70 static HRESULT MyUpdateResource(HANDLE hFile, DWORD cbFile, HANDLE hResourceUpdate, 71 const char *pszResourceType, const char *pszResourceId) 72 { 73 HRESULT hr = E_FAIL; 74 HANDLE hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 75 if (hMap != NULL) 76 { 77 PVOID pvFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, cbFile); 78 if (pvFile) 79 { 80 if (UpdateResourceA(hResourceUpdate, pszResourceType, pszResourceId, 81 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pvFile, cbFile)) 82 hr = S_OK; 83 else 84 fprintf(stderr, "error: UpdateResourceA failed: %lu\n", GetLastError()); 85 86 UnmapViewOfFile(pvFile); 87 } 88 else 89 fprintf(stderr, "error: MapViewOfFile failed: %lu\n", GetLastError()); 76 90 CloseHandle(hMap); 77 91 } 92 else 93 fprintf(stderr, "error: CreateFileMappingW failed: %lu\n", GetLastError()); 78 94 return hr; 79 95 } … … 83 99 { 84 100 HANDLE hFile = INVALID_HANDLE_VALUE; 85 DWORD dwFileSize = 0;86 HRESULT hr = GetFile(pszFilePath, &hFile, & dwFileSize);101 DWORD cbFile = 0; 102 HRESULT hr = GetFile(pszFilePath, &hFile, &cbFile); 87 103 if (SUCCEEDED(hr)) 88 104 { 89 hr = UpdateResource(hFile, dwFileSize, hResourceUpdate, pszResourceType, pszResourceId);105 hr = MyUpdateResource(hFile, cbFile, hResourceUpdate, pszResourceType, pszResourceId); 90 106 if (FAILED(hr)) 91 107 printf("ERROR: Error updating resource for file %s!", pszFilePath); 108 CloseHandle(hFile); 92 109 } 93 110 else 94 111 hr = HRESULT_FROM_WIN32(GetLastError()); 95 96 if (hFile != INVALID_HANDLE_VALUE)97 CloseHandle(hFile);98 112 return hr; 99 113 } … … 130 144 int main(int argc, char* argv[]) 131 145 { 132 HRESULT hr = S_OK; 133 int rcExit = RTEXITCODE_SUCCESS; 134 135 char szSetupStub[_MAX_PATH] = {"VBoxStub.exe"}; 136 char szOutput[_MAX_PATH] = {"VirtualBox-MultiArch.exe"}; 137 HANDLE hUpdate = NULL; 138 139 do /* goto avoidance "loop" */ 140 { 141 printf(VBOX_PRODUCT " Stub Builder v%d.%d.%d.%d\n", 142 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 143 144 if (argc < 2) 145 printf("WARNING: No parameters given! Using default values!\n"); 146 147 VBOXSTUBBUILDPKG stbBuildPkg[VBOXSTUB_MAX_PACKAGES] = {{{0}}}; 148 VBOXSTUBPKG stbPkg[VBOXSTUB_MAX_PACKAGES] = {{0}}; 149 VBOXSTUBPKGHEADER stbHeader = 150 { 151 "vbox$tub", /* File magic. */ 152 1, /* Version. */ 153 0 /* No files yet. */ 154 }; 155 156 for (int i=1; i<argc; i++) 157 { 158 if (!stricmp(argv[i], "-out") && argc > i+1) 159 { 160 hr = StringCchCopy(szOutput, _MAX_PATH, argv[i+1]); 161 i++; 162 } 163 164 else if (!stricmp(argv[i], "-stub") && argc > i+1) 165 { 166 hr = StringCchCopy(szSetupStub, _MAX_PATH, argv[i+1]); 167 i++; 168 } 169 170 else if (!stricmp(argv[i], "-target-all") && argc > i+1) 171 { 172 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]); 173 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_ALL; 174 stbHeader.byCntPkgs++; 175 i++; 176 } 177 178 else if (!stricmp(argv[i], "-target-x86") && argc > i+1) 179 { 180 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]); 181 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_X86; 182 stbHeader.byCntPkgs++; 183 i++; 184 } 185 186 else if (!stricmp(argv[i], "-target-amd64") && argc > i+1) 187 { 188 hr = StringCchCopy(stbBuildPkg[stbHeader.byCntPkgs].szSourcePath, _MAX_PATH, argv[i+1]); 189 stbBuildPkg[stbHeader.byCntPkgs].byArch = VBOXSTUBPKGARCH_AMD64; 190 stbHeader.byCntPkgs++; 191 i++; 192 } 146 /* 147 * Parse arguments. 148 */ 149 const char *pszSetupStub = "VBoxStub.exe"; 150 const char *pszOutput = "VirtualBox-MultiArch.exe"; 151 152 printf(VBOX_PRODUCT " Stub Builder v%d.%d.%d.%d\n", 153 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV); 154 155 struct VBOXSTUBBUILDPKG 156 { 157 const char *pszSrcPath; 158 VBOXSTUBPKGARCH enmArch; 159 } aBuildPkgs[VBOXSTUB_MAX_PACKAGES] = { { NULL } }; 160 VBOXSTUBPKGHEADER StubHdr = 161 { 162 /*.szMagic = */ VBOXSTUBPKGHEADER_MAGIC_SZ, 163 /*.cPackages = */ 0 164 }; 165 166 for (int i = 1; i < argc; i++) 167 { 168 const char *pszArg = argv[i]; 169 if ( strcmp(pszArg, "--help") == 0 170 || strcmp(pszArg, "-help") == 0 171 || strcmp(pszArg, "-h") == 0 172 || strcmp(pszArg, "-?") == 0) 173 { 174 printf("usage: %s -out <installer.exe> -stub <stub.exe> [-target-all <file>] [-target-<arch> <file>]\n", argv[0]); 175 return RTEXITCODE_SUCCESS; 176 } 177 178 /* The remaining options all take a while. */ 179 if ( strcmp(pszArg, "-out") 180 && strcmp(pszArg, "-stub") 181 && strcmp(pszArg, "-target-all") 182 && strcmp(pszArg, "-target-x86") 183 && strcmp(pszArg, "-target-amd64")) 184 { 185 fprintf(stderr, "syntax error: Invalid parameter: %s\n", argv[i]); 186 return RTEXITCODE_SYNTAX; 187 } 188 189 i++; 190 if (i >= argc) 191 { 192 fprintf(stderr, "syntax error: Option '%s' takes a value argument!\n", pszArg); 193 return RTEXITCODE_SYNTAX; 194 } 195 const char *pszValue = argv[i]; 196 197 /* Process the individual options. */ 198 if (strcmp(pszArg, "-out") == 0) 199 pszOutput = pszValue; 200 else if (strcmp(pszArg, "-stub") == 0) 201 pszSetupStub = pszValue; 202 else 203 { 204 if (StubHdr.cPackages >= RT_ELEMENTS(aBuildPkgs)) 205 { 206 fprintf(stderr, "error: Too many packages specified!\n"); 207 return RTEXITCODE_FAILURE; 208 } 209 aBuildPkgs[StubHdr.cPackages].pszSrcPath = pszValue; 210 if (strcmp(pszArg, "-target-all") == 0) 211 aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_ALL; 212 else if (strcmp(pszArg, "-target-amd64") == 0) 213 aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_AMD64; 214 else if (strcmp(pszArg, "-target-x86") == 0) 215 aBuildPkgs[StubHdr.cPackages].enmArch = VBOXSTUBPKGARCH_X86; 193 216 else 194 217 { 195 printf("ERROR: Invalid parameter: %s\n", argv[i]); 196 hr = E_INVALIDARG; 197 break; 198 } 199 if (FAILED(hr)) 200 { 201 printf("ERROR: StringCchCopy failed: %#lx\n", hr); 202 break; 203 } 204 } 205 if (FAILED(hr)) 206 break; 207 208 if (stbHeader.byCntPkgs <= 0) 209 { 210 printf("ERROR: No packages defined! Exiting.\n"); 211 break; 212 } 213 214 printf("Stub: %s\n", szSetupStub); 215 printf("Output: %s\n", szOutput); 216 printf("# Packages: %u\n", stbHeader.byCntPkgs); 217 218 if (!CopyFile(szSetupStub, szOutput, FALSE)) 219 { 220 hr = HRESULT_FROM_WIN32(GetLastError()); 221 printf("ERROR: Could not create stub loader: %#lx\n", hr); 222 break; 223 } 224 225 hUpdate = BeginUpdateResource(szOutput, FALSE); 226 227 PVBOXSTUBPKG pPackage = stbPkg; 228 char szHeaderName[_MAX_PATH] = {0}; 229 230 for (BYTE i = 0; i < stbHeader.byCntPkgs; i++) 231 { 232 printf("Integrating (Platform %d): %s\n", stbBuildPkg[i].byArch, stbBuildPkg[i].szSourcePath); 233 234 /* Construct resource name. */ 235 hr = StringCchPrintf(pPackage->szResourceName, _MAX_PATH, "BIN_%02d", i); 236 pPackage->byArch = stbBuildPkg[i].byArch; 218 fprintf(stderr, "internal error: %u\n", __LINE__); 219 return RTEXITCODE_FAILURE; 220 } 221 StubHdr.cPackages++; 222 } 223 } 224 225 if (StubHdr.cPackages == 0) 226 { 227 fprintf(stderr, "syntax error: No packages specified! Exiting.\n"); 228 return RTEXITCODE_SYNTAX; 229 } 230 231 printf("Stub: %s\n", pszSetupStub); 232 printf("Output: %s\n", pszOutput); 233 printf("# Packages: %u\n", StubHdr.cPackages); 234 235 /* 236 * Copy the stub over the output file. 237 */ 238 if (!CopyFile(pszSetupStub, pszOutput, FALSE)) 239 { 240 fprintf(stderr, "ERROR: Could not copy the stub loader: %lu\n", GetLastError()); 241 return RTEXITCODE_SYNTAX; 242 } 243 244 /* 245 * Start updating the resources of the output file. 246 */ 247 HANDLE hUpdate = BeginUpdateResourceA(pszOutput, FALSE); 248 if (hUpdate) 249 { 250 /* 251 * Add the file one by one to the output file. 252 */ 253 HRESULT hrc = S_OK; 254 for (BYTE i = 0; i < StubHdr.cPackages; i++) 255 { 256 printf("Integrating (Platform %d): %s\n", aBuildPkgs[i].enmArch, aBuildPkgs[i].pszSrcPath); 257 258 /* 259 * Create the package header. 260 */ 261 VBOXSTUBPKG Package = {0}; 262 Package.enmArch = aBuildPkgs[i].enmArch; 263 264 /* The resource name */ 265 hrc = StringCchPrintf(Package.szResourceName, sizeof(Package.szResourceName), "BIN_%02d", i); 266 if (FAILED(hrc)) 267 { 268 fprintf(stderr, "Internal error: %u\n", __LINE__); 269 break; 270 } 237 271 238 272 /* Construct final name used when extracting. */ 239 hr = StringCchCopy(pPackage->szFileName, _MAX_PATH, MyPathFilename(stbBuildPkg[i].szSourcePath)); 240 241 /* Integrate header into binary. */ 242 hr = StringCchPrintf(szHeaderName, _MAX_PATH, "HDR_%02d", i); 243 hr = UpdateResource(hUpdate, RT_RCDATA, szHeaderName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pPackage, sizeof(VBOXSTUBPKG)); 244 245 /* Integrate file into binary. */ 246 hr = IntegrateFile(hUpdate, RT_RCDATA, pPackage->szResourceName, stbBuildPkg[i].szSourcePath); 247 if (FAILED(hr)) 248 { 249 printf("ERROR: Could not integrate binary %s (%s): %#lx\n", 250 pPackage->szResourceName, pPackage->szFileName, hr); 251 rcExit = RTEXITCODE_FAILURE; 252 } 253 254 pPackage++; 255 } 256 257 if (FAILED(hr)) 258 break; 259 260 if (!UpdateResource(hUpdate, RT_RCDATA, "MANIFEST", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &stbHeader, sizeof(VBOXSTUBPKGHEADER))) 261 { 262 hr = HRESULT_FROM_WIN32(GetLastError()); 263 break; 264 } 265 266 if (!EndUpdateResource(hUpdate, FALSE)) 267 { 268 hr = HRESULT_FROM_WIN32(GetLastError()); 269 break; 270 } 271 272 printf("Integration done!\n"); 273 274 } while (0); 275 276 hUpdate = NULL; 277 278 if (FAILED(hr)) 279 { 280 printf("ERROR: Building failed! Last error: %lu\n", GetLastError()); 281 rcExit = RTEXITCODE_FAILURE; 282 } 283 return rcExit; 284 } 273 hrc = StringCchCopy(Package.szFilename, sizeof(Package.szFilename), MyPathFilename(aBuildPkgs[i].pszSrcPath)); 274 if (FAILED(hrc)) 275 { 276 fprintf(stderr, "ERROR: Filename is too long: %s\n", aBuildPkgs[i].pszSrcPath); 277 break; 278 } 279 280 /* 281 * Add the package header to the binary. 282 */ 283 char szHeaderName[32]; 284 hrc = StringCchPrintf(szHeaderName, sizeof(szHeaderName), "HDR_%02d", i); 285 if (FAILED(hrc)) 286 { 287 fprintf(stderr, "Internal error: %u\n", __LINE__); 288 break; 289 } 290 291 if (!UpdateResourceA(hUpdate, RT_RCDATA, szHeaderName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 292 &Package, sizeof(Package))) 293 { 294 fprintf(stderr, "ERROR: UpdateResourceA failed for the package header: %lu\n", GetLastError()); 295 hrc = E_FAIL; 296 break; 297 } 298 299 /* 300 * Add the file content under the BIN_xx resource name. 301 */ 302 hrc = IntegrateFile(hUpdate, RT_RCDATA, Package.szResourceName, aBuildPkgs[i].pszSrcPath); 303 if (FAILED(hrc)) 304 break; 305 } 306 if (SUCCEEDED(hrc)) 307 { 308 /* 309 * Now add the header/manifest and complete the operation. 310 */ 311 if (UpdateResourceA(hUpdate, RT_RCDATA, "MANIFEST", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 312 &StubHdr, sizeof(StubHdr))) 313 { 314 if (EndUpdateResourceA(hUpdate, FALSE /*fDiscard*/)) 315 { 316 printf("Successfully created the installer\n"); 317 return RTEXITCODE_SUCCESS; 318 } 319 fprintf(stderr, "ERROR: EndUpdateResourceA failed: %lu\n", GetLastError()); 320 } 321 else 322 fprintf(stderr, "ERROR: UpdateResourceA failed for the installer header/manifest: %lu\n", GetLastError()); 323 } 324 325 EndUpdateResourceA(hUpdate, TRUE /*fDiscard*/); 326 hUpdate = NULL; 327 } 328 else 329 fprintf(stderr, "error: BeginUpdateResource failed: %lu\n", GetLastError()); 330 return RTEXITCODE_FAILURE; 331 } -
trunk/src/VBox/Installer/win/StubBld/VBoxStubBld.h
r96407 r96571 32 32 #endif 33 33 34 #include <iprt/types.h> 35 #include <iprt/assertcompile.h> 36 37 /**/ 34 38 #define VBOXSTUB_MAX_PACKAGES 128 35 39 40 /** */ 41 #define VBOXSTUBPKGHEADER_MAGIC_SZ "VBoxInstV1\0\0\0\0" 42 43 /** 44 * VBox installer stub header, aka "MANIFEST". 45 * 46 * This just holds the number of packages present in the image. 47 */ 36 48 typedef struct VBOXSTUBPKGHEADER 37 49 { 38 /** Some magic string not defined by this header? Turns out it's a write only 39 * field... */ 40 char szMagic[9]; 41 /* Inbetween szMagic and dwVersion there are 3 bytes of implicit padding. */ 42 /** Some version number not defined by this header? Also write only field. 43 * Should be a uint32_t, not DWORD. */ 44 DWORD dwVersion; 45 /** Number of packages following the header. byte is prefixed 'b', not 'by'! 46 * Use uint8_t instead of BYTE. */ 47 BYTE byCntPkgs; 48 /* There are 3 bytes of implicit padding here. */ 50 /** Magic value/string (VBOXSTUBPKGHEADER_MAGIC_SZ) */ 51 char szMagic[11 + 4]; 52 /** Number of packages following the header. */ 53 uint8_t cPackages; 49 54 } VBOXSTUBPKGHEADER; 55 AssertCompileSize(VBOXSTUBPKGHEADER, 16); 50 56 typedef VBOXSTUBPKGHEADER *PVBOXSTUBPKGHEADER; 51 57 52 58 typedef enum VBOXSTUBPKGARCH 53 59 { 54 VBOXSTUBPKGARCH_ALL = 0, 60 /** Always extract. */ 61 VBOXSTUBPKGARCH_ALL = 1, 62 /** Extract on x86 hosts. */ 55 63 VBOXSTUBPKGARCH_X86, 64 /** Extract on AMD64 hosts. */ 56 65 VBOXSTUBPKGARCH_AMD64 57 66 } VBOXSTUBPKGARCH; 58 67 68 /** 69 * Package header/descriptor. 70 * 71 * This is found as "HDR_xx" where xx is replaced by the decimal package number, 72 * zero padded to two digits. 73 */ 59 74 typedef struct VBOXSTUBPKG 60 75 { 61 BYTE byArch; 62 /** Probably the name of the PE resource or something, read the source to 63 * find out for sure. Don't use _MAX_PATH, define your own max lengths! */ 64 char szResourceName[_MAX_PATH]; 65 char szFileName[_MAX_PATH]; 76 /** The architecture for the file. */ 77 VBOXSTUBPKGARCH enmArch; 78 /** The name of the resource holding the file bytes. 79 * This is a pointless field, because the resource name is "BIN_xx" 80 * corresponding to the name of the resource containing this struct. */ 81 char szResourceName[28]; 82 /** The filename. */ 83 char szFilename[224]; 66 84 } VBOXSTUBPKG; 85 AssertCompileSize(VBOXSTUBPKG, 256); 67 86 typedef VBOXSTUBPKG *PVBOXSTUBPKG; 68 87 69 /* Only for construction. */70 /* Since it's only used by VBoxStubBld.cpp, why not just keep it there? */71 72 typedef struct VBOXSTUBBUILDPKG73 {74 char szSourcePath[_MAX_PATH];75 BYTE byArch;76 } VBOXSTUBBUILDPKG;77 typedef VBOXSTUBBUILDPKG *PVBOXSTUBBUILDPKG;78 79 88 #endif /* !VBOX_INCLUDED_SRC_StubBld_VBoxStubBld_h */
Note:
See TracChangeset
for help on using the changeset viewer.