From: Bernhard Reiter Subject: [2/2] imagehlp: Implement (parts of) BindImageEx (try 10) Message-Id: <53B19B4A.6010401@raz.or.at> Date: Mon, 30 Jun 2014 19:15:54 +0200 Polish some more. From 740c4f4f95a908d7c08a2f407e160d523fa7f13c Mon Sep 17 00:00:00 2001 From: Bernhard Reiter Date: Wed, 9 Apr 2014 00:52:31 +0200 Subject: Implement parts of BindImageEx so at least freezing Python scripts works. Fixes http://bugs.winehq.org/show_bug.cgi?id=3591 --- dlls/imagehlp/modify.c | 79 +++++++++++++++++++++++++++++++++++++++++++-- dlls/imagehlp/tests/image.c | 30 ++++++++--------- 2 files changed, 92 insertions(+), 17 deletions(-) diff --git a/dlls/imagehlp/modify.c b/dlls/imagehlp/modify.c index debccc0..2b69fcf 100644 --- a/dlls/imagehlp/modify.c +++ b/dlls/imagehlp/modify.c @@ -29,11 +29,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); +PVOID WINAPI ImageDirectoryEntryToDataEx( PVOID base, BOOLEAN image, USHORT dir, + PULONG size, PIMAGE_SECTION_HEADER *section ); static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount); - /*********************************************************************** * BindImage (IMAGEHLP.@) + * + * NOTES + * See BindImageEx */ BOOL WINAPI BindImage( PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath) @@ -43,15 +47,86 @@ BOOL WINAPI BindImage( /*********************************************************************** * BindImageEx (IMAGEHLP.@) + * + * Compute the virtual address of each function imported by a PE image + * + * PARAMS + * + * Flags [in] Bind options + * ImageName [in] File name of the image to be bound + * DllPath [in] Root of the fallback search path in case the ImageName file cannot be opened + * SymbolPath [in] Symbol file root search path + * StatusRoutine [in] Pointer to a status routine which will be called during the binding process + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * The main purpose of this stub implementation is to allow "freezing" of Python packages + * (as performed by cx_Freeze or py2exe) which usually invokes BindImageEx to determine what DLLs + * to add to the frozen package by passing a StatusRoutine to it that listens for the + * BindImportModule and BindImportProcedure statuses to determine the imported modules and + * procedures. */ BOOL WINAPI BindImageEx( DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath, PIMAGEHLP_STATUS_ROUTINE StatusRoutine) { - FIXME("(%d, %s, %s, %s, %p): stub\n", + LOADED_IMAGE loadedImage; + const IMAGE_IMPORT_DESCRIPTOR *importDesc; + ULONG size; + CHAR DllFullName[MAX_PATH]; + + FIXME("(%d, %s, %s, %s, %p)\n", Flags, debugstr_a(ImageName), debugstr_a(DllPath), debugstr_a(SymbolPath), StatusRoutine ); + + if (!(MapAndLoad( ImageName, DllPath, &loadedImage, TRUE, TRUE ))) return FALSE; + + if (!(importDesc = ImageDirectoryEntryToDataEx( loadedImage.MappedAddress, FALSE, + IMAGE_DIRECTORY_ENTRY_IMPORT, &size, NULL ))) + return TRUE; /* No imported modules means nothing to bind, so we're done. */ + + for (; importDesc->Name && importDesc->OriginalFirstThunk; ++importDesc) + { + IMAGE_THUNK_DATA *thunk; + char *DllName = ImageRvaToVa( loadedImage.FileHeader, loadedImage.MappedAddress, + importDesc->Name, NULL ); + + (*StatusRoutine)( BindImportModule, ImageName, DllName, 0, 0); + + FIXME("Actual image loading not implemented, only looking up its location instead\n"); + if (!SearchPathA( DllPath, DllName, NULL, sizeof(DllFullName), DllFullName, NULL)) + { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + thunk = ImageRvaToVa( loadedImage.FileHeader, loadedImage.MappedAddress, + importDesc->OriginalFirstThunk, NULL ); + + for (; thunk->u1.Function; ++thunk) + { + if(thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) + { + /* Ordinal, i.e. unnamed function. Not sure if/how to pass this on to StatusRoutine... */ + /* DWORD ordinal = (DWORD) (thunk->u1.Ordinal & (~IMAGE_ORDINAL_FLAG)); */ + } + else + { + IMAGE_IMPORT_BY_NAME *funcNameStruct = + ImageRvaToVa( loadedImage.FileHeader, loadedImage.MappedAddress, + thunk->u1.AddressOfData, NULL ); + (*StatusRoutine)( BindImportProcedure, ImageName, DllFullName, 0, + (ULONG_PTR) funcNameStruct->Name ); + FIXME("Actual binding not implemented yet\n"); + } + } + } + + UnMapAndLoad( &loadedImage ); return TRUE; } diff --git a/dlls/imagehlp/tests/image.c b/dlls/imagehlp/tests/image.c index d93130c..3ae8611 100644 --- a/dlls/imagehlp/tests/image.c +++ b/dlls/imagehlp/tests/image.c @@ -286,9 +286,9 @@ BOOL WINAPI TestingStatusRoutine(IMAGEHLP_STATUS_REASON reason, PSTR ImageName, status_routine_called[reason]++; - todo_wine ok((reason == BindImportModule) || (reason == BindImportProcedure) || - (reason == BindForwarderNOT), "expected reason to be one of BindImportModule, " - "BindImportProcedure, or BindForwarderNOT, got %d\n", reason); + ok((reason == BindImportModule) || (reason == BindImportProcedure) || + (reason == BindForwarderNOT), "expected reason to be one of BindImportModule, " + "BindImportProcedure, or BindForwarderNOT, got %d\n", reason); switch(reason) { @@ -392,10 +392,10 @@ static void test_bind_image_ex(void) SetLastError(0xdeadbeef); ret = pBindImageEx(BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE | BIND_ALL_IMAGES, temp_file, NULL, NULL, (void *)TestingStatusRoutine); - todo_wine ok(!ret && ((GetLastError() == ERROR_FILE_NOT_FOUND) || - (GetLastError() == ERROR_INVALID_PARAMETER)), - "expected ERROR_FILE_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n", - GetLastError()); + ok(!ret && ((GetLastError() == ERROR_FILE_NOT_FOUND) || + (GetLastError() == ERROR_INVALID_PARAMETER)), + "expected ERROR_FILE_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n", + GetLastError()); file = create_temp_file(temp_file); if (file == INVALID_HANDLE_VALUE) @@ -414,17 +414,17 @@ static void test_bind_image_ex(void) NULL, (void *)TestingStatusRoutine); ok(ret, "BindImageEx failed: %d\n", GetLastError()); - todo_wine ok(status_routine_called[BindImportModule] == 1, - "Expected StatusRoutine to be called once with reason BindImportModule, " - "but it was called %d times\n", status_routine_called[BindImportModule]); + ok(status_routine_called[BindImportModule] == 1, + "Expected StatusRoutine to be called once with reason BindImportModule, " + "but it was called %d times\n", status_routine_called[BindImportModule]); /* Under wvistau64 (64 bit image), w2008s64 (64 bit image) and w7pro64 (64 bit image), * StatusRoutine is called with reason BindForwarderNOT instead of BindImportProcedure. */ - todo_wine ok((status_routine_called[BindImportProcedure] == 1) || - (status_routine_called[BindForwarderNOT] == 1), - "Expected StatusRoutine to be called once with reason BindImportProcedure or " - "BindForwarderNOT, but it was called %d and %d times, respectively\n", - status_routine_called[BindImportProcedure], status_routine_called[BindForwarderNOT]); + ok((status_routine_called[BindImportProcedure] == 1) || + (status_routine_called[BindForwarderNOT] == 1), + "Expected StatusRoutine to be called once with reason BindImportProcedure or " + "BindForwarderNOT, but it was called %d and %d times, respectively\n", + status_routine_called[BindImportProcedure], status_routine_called[BindForwarderNOT]); DeleteFileA(temp_file); } -- 1.9.1