Author Topic: Using 32-bit code in 64-bit land  (Read 1239 times)

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4750
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Using 32-bit code in 64-bit land
« Reply #15 on: March 13, 2017, 11:00:39 PM »
For secure inter app communication you use a private message that is unique to your app and the other you are communicating with.

invoke PostMessage,HWND_BROADCAST,PM_YOURMESSAGE,0,0
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

jj2007

  • Member
  • *****
  • Posts: 7453
  • Assembler is fun ;-)
    • MasmBasic
Re: Using 32-bit code in 64-bit land
« Reply #16 on: March 14, 2017, 01:10:05 AM »
On topic: Does anybody have experience with ZwExtendSection? Apparently, it's the only way to implement a realloc on a memory-mapped file, but it's kind of undocumented...

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 4750
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Using 32-bit code in 64-bit land
« Reply #17 on: March 14, 2017, 02:06:23 AM »
With a bit of messing around you could do this with the existing capacity without having to go to risky undocumented functions. Use messaging to tell both apps to shut down the existing MMF, send another message with the new size then send a message telling both to create a new MMF. Written properly it would work OK and probably be easily fast enough.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

jj2007

  • Member
  • *****
  • Posts: 7453
  • Assembler is fun ;-)
    • MasmBasic
Re: Using 32-bit code in 64-bit land
« Reply #18 on: March 14, 2017, 03:23:03 AM »
Complicated. Here is a shorter option:
Code: [Select]
mov rax, 8000000000
jinvoke CreateFileMapping, INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, rax, Chr$("~TmpObject")

Works fine and returns immediately.

adeyblue

  • Member
  • **
  • Posts: 88
    • Airesoft
Re: Using 32-bit code in 64-bit land
« Reply #19 on: March 14, 2017, 10:37:48 AM »
On topic: Does anybody have experience with ZwExtendSection? Apparently, it's the only way to implement a realloc on a memory-mapped file, but it's kind of undocumented...

It basically does this part of the CreateFileMapping documentation, but on demand.
Quote
If an application specifies a size for the file mapping object that is larger than the size of the actual named file on disk, the file on disk is increased to match the specified size of the file mapping object

It is only for mapped disk files that you've opened for writing. It'll fail if you instead pass NULL as the file handle to CreateFileMapping. Here's an example.

Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

extern "C"
DECLSPEC_IMPORT
long
WINAPI
NtExtendSection(HANDLE hMap, PLARGE_INTEGER pNewSize);

int main()
{
HANDLE hFile = CreateFileW(L"file.txt", GENERIC_ALL, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
if(hFile == INVALID_HANDLE_VALUE) {return printf("CreateFile fail - error %lu!\n", GetLastError());}
SetFilePointer(hFile, 1, NULL, FILE_BEGIN); // You can't map a 0 length file
SetEndOfFile(hFile);
DWORD size = GetFileSize(hFile, NULL);
printf("Original file size is %lu\n", size);
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 8192, NULL);
if(hMapping == NULL) {return printf("CreateFileMapping fail - error %lu!\n", GetLastError());}
size = GetFileSize(hFile, NULL);
printf("After CreateFileMapping, file size is %lu\n", size);
HANDLE hAllPermHandle = NULL;
// docs lie, CreateFileMapping doesn't create an all access handle
// it doesn't have SECTION_EXTEND_SIZE right which is required for NtExtendSection
// without this, NtExtendSection will fail with 0xc0000022 (STATUS_ACCESS_DENIED)
DuplicateHandle(GetCurrentProcess(), hMapping, GetCurrentProcess(), &hAllPermHandle, SECTION_ALL_ACCESS, FALSE, DUPLICATE_CLOSE_SOURCE);
if(hAllPermHandle == NULL) {return printf("DuplicateHandle fail - error %lu!\n", GetLastError());}
hMapping = hAllPermHandle;
PVOID pMapping = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
if(pMapping == NULL) {return printf("MapFileMapping fail - error %lu!\n", GetLastError());}
MEMORY_BASIC_INFORMATION mbi = {0};
VirtualQuery(pMapping, &mbi, sizeof(mbi));
printf("Mapped size is %Iu\n", mbi.RegionSize);

LARGE_INTEGER newSize = {16384};
long stat = NtExtendSection(hMapping, &newSize);
if(stat < 0) {return printf("NtExtendSection fail - err %#x\n", stat);}
size = GetFileSize(hFile, NULL);
printf("After NtExtendSection file size is %lu\n", size);
VirtualQuery(pMapping, &mbi, sizeof(mbi));
        // It doesn't update the mapped memory size though, you have to map any new bits yourself
printf("Mapped size after NtExtendSection is %Iu\n", mbi.RegionSize);
}

jj2007

  • Member
  • *****
  • Posts: 7453
  • Assembler is fun ;-)
    • MasmBasic
Re: Using 32-bit code in 64-bit land
« Reply #20 on: March 14, 2017, 11:16:43 AM »
It'll fail if you instead pass NULL as the file handle to CreateFileMapping.

You mean -1, INVALID_HANDLE_VALUE?

jj2007

  • Member
  • *****
  • Posts: 7453
  • Assembler is fun ;-)
    • MasmBasic
Re: Using 32-bit code in 64-bit land
« Reply #21 on: March 15, 2017, 04:23:49 AM »
Just for fun, attached a 64-bit application that calls a 32-bit server which translates Windows.inc into a string array using Recall. The 64-bit program prints the first n strings of the array to the console.

To test it, extract all files to a folder and start GetStringsFrom32BitLib.exe; afterwards, press O (like open) to see the first 39 strings and timings. For me (Core i5), it's around 100 ticks with printing 33 lines, and around 8 ticks when printing only one line (see source, line 93, .Until ct>32). Task manager looks OK, even if I keep the "O" pressed.

Every time you "open" the file, a 800MB MMF gets created (and closed):
   mov rax, 800000000
   jinvoke CreateFileMapping, INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, rax, Chr$("~TmpObject")

adeyblue

  • Member
  • **
  • Posts: 88
    • Airesoft
Re: Using 32-bit code in 64-bit land
« Reply #22 on: March 15, 2017, 04:57:48 AM »
It'll fail if you instead pass NULL as the file handle to CreateFileMapping.

You mean -1, INVALID_HANDLE_VALUE?

NULL is accepted as -1 (or rather -1 is converted to NULL), so they're equivalent for CreateFileMapping.

jj2007

  • Member
  • *****
  • Posts: 7453
  • Assembler is fun ;-)
    • MasmBasic
Re: Using 32-bit code in 64-bit land
« Reply #23 on: March 15, 2017, 06:05:20 AM »
NULL is accepted as -1 (or rather -1 is converted to NULL)

You have hacked the CreateFileMapping source :eusa_naughty:

Under the hood, 000007FEFD3F19D2:
Code: [Select]
000007FEFD3F19C4 | 4C 8D 4C 24 40                       | lea r9, qword ptr ss:[rsp+40]                 |
000007FEFD3F19C9 | 89 44 24 40                          | mov dword ptr ss:[rsp+40], eax                |
000007FEFD3F19CD | 44 89 6C 24 44                       | mov dword ptr ss:[rsp+44], r13d               |
000007FEFD3F19D2 | 48 83 FD FF                          | cmp rbp, FFFFFFFFFFFFFFFF                     |
000007FEFD3F19D6 | 0F 84 C4 00 00 00                    | je 7FEFD3F1AA0                                |
@@:
000007FEFD3F19DC | 83 FE FF                             | cmp esi, FFFFFFFF                             |
000007FEFD3F19DF | 0F 85 23 D5 00 00                    | jne 7FEFD3FEF08                               |
...
000007FEFD3F1AA0 | 4D 85 C9                             | test r9, r9                                   |
000007FEFD3F1AA3 | 0F 84 E5 D3 00 00                    | je 7FEFD3FEE8E                                |
000007FEFD3F1AA9 | 33 ED                                | xor ebp, ebp                                  |
000007FEFD3F1AAB | E9 2C FF FF FF                       | jmp @B   ;7FEFD3F19DC                               |

So -1 and 0 work - and no other value :t

Slightly odd the test r9, r9 at AA0; there is no such test if you pass handle zero, and with the lea r9, [rsp+40], it can never be zero ::)

Btw this is the limit on my 4GB RAM machine - slightly under one GB:
Code: [Select]
mov rax, 1020000000
jinvoke CreateFileMapping, -1, NULL, PAGE_READWRITE, 0, rax, Chr$("~TmpObject")