and access violation in secdrv.sys
To perform relocation, we need to be able to write to memory, but there
appears to be some sort of problem with this that causes wine to hang.
I'm attaching your original patch, plus an updated one that Laurent Pinchar and
I have come up with, it should work *in theory*, but it doesn't.
Laurent has suggested that maybe it would if the image was aligned to a page boundary,
but I'm to tired to look into it now.
I'm cc'ing wine-devel, ideas/patches welcome.
Ivan.
diff -urN wine/dlls/ntdll/virtual.c new/dlls/ntdll/virtual.c
--- wine/dlls/ntdll/virtual.c 2004-12-02 19:19:25.000000000 +0100
+++ new/dlls/ntdll/virtual.c 2005-01-01 20:59:09.153375723 +0100
@@ -829,6 +829,7 @@
off_t pos;
struct file_view *view = NULL;
char *ptr;
+ BOOL native = FALSE;
/* zero-map the whole range */
@@ -882,6 +883,27 @@
goto error;
}
+ /* check for non page-aligned binary */
+
+ if (nt->OptionalHeader.SectionAlignment <= page_mask)
+ {
+ /* unaligned sections, this happens for native subsystem binaries */
+ /* in that case Windows simply maps in the whole file */
+
+ native = TRUE;
+ if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | PROT_WRITE | VPROT_READ,
+ removable ) != STATUS_SUCCESS) goto error;
+
+ /* check that all sections are loaded at the right offset */
+ for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
+ {
+ if (sec[i].VirtualAddress != sec[i].PointerToRawData)
+ goto error; /* Windows refuses to load in that case too */
+ }
+
+ goto done;
+ }
+
/* map all the sections */
for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
@@ -962,6 +984,7 @@
}
}
+ done:
/* perform base relocation, if necessary */
@@ -994,23 +1017,30 @@
}
}
+ /* set the image protections */
+
+ if (!native)
+ {
+ sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
+ for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
+ {
+ DWORD size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
+ BYTE vprot = VPROT_COMMITTED;
+ if (sec->Characteristics & IMAGE_SCN_MEM_READ) vprot |= VPROT_READ;
+ if (sec->Characteristics & IMAGE_SCN_MEM_WRITE) vprot |= VPROT_READ|VPROT_WRITECOPY;
+ if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
+ VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
+ }
+ }
+ else
+ VIRTUAL_SetProt( view, ptr, total_size,
+ VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );
+
if (!removable) /* don't keep handle open on removable media */
NtDuplicateObject( GetCurrentProcess(), hmapping,
GetCurrentProcess(), &view->mapping,
0, 0, DUPLICATE_SAME_ACCESS );
- /* set the image protections */
-
- sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
- for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
- {
- DWORD size = ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
- BYTE vprot = VPROT_COMMITTED;
- if (sec->Characteristics & IMAGE_SCN_MEM_READ) vprot |= VPROT_READ;
- if (sec->Characteristics & IMAGE_SCN_MEM_WRITE) vprot |= VPROT_READ|VPROT_WRITECOPY;
- if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
- VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
- }
RtlLeaveCriticalSection( &csVirtual );
*addr_ptr = ptr;
diff -urN wine/server/mapping.c new/server/mapping.c
--- wine/server/mapping.c 1 May 2004 02:50:06 -0000
+++ new/server/mapping.c 25 Dec 2004 17:09:01 -0000
@@ -103,8 +103,10 @@ static void init_page_size(void)
#define ROUND_ADDR(addr) \
((int)(addr) & ~page_mask)
-#define ROUND_SIZE(addr,size) \
- (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
+#define ROUND_SIZE_MASK(addr,size,mask) \
+ (((int)(size) + ((int)(addr) & (mask)) + (mask)) & ~(mask))
+
+#define ROUND_SIZE(addr,size) ROUND_SIZE_MASK( addr, size, page_mask )
/* find the shared PE mapping for a given mapping */
@@ -236,7 +238,8 @@ static int get_image_params( struct mapp
mapping->size_low = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage );
mapping->size_high = 0;
mapping->base = (void *)nt.OptionalHeader.ImageBase;
- mapping->header_size = ROUND_SIZE( mapping->base, nt.OptionalHeader.SizeOfHeaders );
+ mapping->header_size = ROUND_SIZE_MASK( mapping->base, nt.OptionalHeader.SizeOfHeaders,
+ nt.OptionalHeader.SectionAlignment - 1 );
mapping->protect = VPROT_IMAGE;
/* sanity check */
----------------------------------------------------------------
Index: dlls/ntdll/virtual.c
===================================================================
RCS file: /opt/cvs-commit/wine/dlls/ntdll/virtual.c,v
retrieving revision 1.42
diff -u -p -r1.42 virtual.c
--- dlls/ntdll/virtual.c 2 Dec 2004 18:19:25 -0000 1.42
+++ dlls/ntdll/virtual.c 25 Dec 2004 17:09:01 -0000
@@ -882,6 +882,30 @@ static NTSTATUS map_image( HANDLE hmappi
goto error;
}
+ /* check for non page-aligned binary */
+
+ if (nt->OptionalHeader.SectionAlignment <= page_mask)
+ {
+ /* unaligned sections, this happens for native subsystem binaries */
+ /* in that case Windows simply maps in the whole file */
+
+ if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ,
+ removable ) != STATUS_SUCCESS) goto error;
+
+ /* check that all sections are loaded at the right offset */
+ for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
+ {
+ if (sec[i].VirtualAddress != sec[i].PointerToRawData)
+ goto error; /* Windows refuses to load in that case too */
+ }
+
+ /* set the image protections */
+ VIRTUAL_SetProt( view, ptr, total_size,
+ VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY | VPROT_EXEC );
+ goto done;
+ }
+
+
/* map all the sections */
for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
@@ -994,11 +1018,6 @@ static NTSTATUS map_image( HANDLE hmappi
}
}
- if (!removable) /* don't keep handle open on removable media */
- NtDuplicateObject( GetCurrentProcess(), hmapping,
- GetCurrentProcess(), &view->mapping,
- 0, 0, DUPLICATE_SAME_ACCESS );
-
/* set the image protections */
sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
@@ -1011,6 +1030,13 @@ static NTSTATUS map_image( HANDLE hmappi
if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) vprot |= VPROT_EXEC;
VIRTUAL_SetProt( view, ptr + sec->VirtualAddress, size, vprot );
}
+
+ done:
+ if (!removable) /* don't keep handle open on removable media */
+ NtDuplicateObject( GetCurrentProcess(), hmapping,
+ GetCurrentProcess(), &view->mapping,
+ 0, 0, DUPLICATE_SAME_ACCESS );
+
RtlLeaveCriticalSection( &csVirtual );
*addr_ptr = ptr;
Index: server/mapping.c
===================================================================
RCS file: /opt/cvs-commit/wine/server/mapping.c,v
retrieving revision 1.47
diff -u -p -r1.47 mapping.c
--- server/mapping.c 1 May 2004 02:50:06 -0000 1.47
+++ server/mapping.c 25 Dec 2004 17:09:01 -0000
@@ -103,8 +103,10 @@ static void init_page_size(void)
#define ROUND_ADDR(addr) \
((int)(addr) & ~page_mask)
-#define ROUND_SIZE(addr,size) \
- (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask)
+#define ROUND_SIZE_MASK(addr,size,mask) \
+ (((int)(size) + ((int)(addr) & (mask)) + (mask)) & ~(mask))
+
+#define ROUND_SIZE(addr,size) ROUND_SIZE_MASK( addr, size, page_mask )
/* find the shared PE mapping for a given mapping */
@@ -236,7 +238,8 @@ static int get_image_params( struct mapp
mapping->size_low = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage );
mapping->size_high = 0;
mapping->base = (void *)nt.OptionalHeader.ImageBase;
- mapping->header_size = ROUND_SIZE( mapping->base, nt.OptionalHeader.SizeOfHeaders );
+ mapping->header_size = ROUND_SIZE_MASK( mapping->base, nt.OptionalHeader.SizeOfHeaders,
+ nt.OptionalHeader.SectionAlignment - 1 );
mapping->protect = VPROT_IMAGE;
/* sanity check */
