Therefore, I decided to use WinDbg to attach to the Windows Management Instrumentation process "Wmiprvse.exe" and change the result for the query of the memory size.
There are different possibilities to attach to a process in WinDbg which are described here. In my case the process was already running and I have been simply attaching in WinDbg. I had to attach to the process which was running under the NT AUTHORITY\NETWORK SERVICE account because my installer was executed on another machine and asked remotely the WMI interface for the memory size. If you want to attach to the process automatically when it starts up, you have to use the Remote Debugging techniques of WinDbg with NTSD which are described here. Network services are not allowed to interact with the desktop, therefore using gflags or the registry to automatically launch windbg would not work because the Window of WinDbg would never pop up.
After you attached to the "Wmiprvse.exe" process, you have to make sure that the symbols for the Microsoft libraries are available. Simply enter the following command in WinDbg to load the symbols on demand from the Microsoft Symbol Server.
.sympath SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols
After that we can set a breakpoint for the GlobalMemoryStatusEx method which will be eventually called by the Wmiprvse.exe process to retrieve the memory size.
bp kernel32!GlobalMemoryStatusEx
Now you can simply resume the process with the g-command. The process is running now with the debugger attached with the breakpoint at the GlobalMemoryStatusEx method.
g
At this point of time the installer can be triggered to query for the memory size of the machine. After that you should immediately see in the WinDbg window the following output:
Breakpoint 0 hit kernel32!GlobalMemoryStatusEx: 00000000`76f38928 ff2522500900 jmp qword ptr [kernel32!_imp_GlobalMemoryStatusEx (00000000`76fcd950)] ds:00000000`76fcd950={KERNELBASE!GlobalMemoryStatusEx (000007fe`fd845c90)}
The breakpoint has been hit and now I have been stepping through the assembler commands of the GlobalMemoryStatusEx methods with the WinDbg p-command. Here you see the step-by-step debugging output:
0:006> p KERNELBASE!GlobalMemoryStatusEx: 000007fe`fd845c90 4881ece8000000 sub rsp,0E8h 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x7: 000007fe`fd845c97 833940 cmp dword ptr [rcx],40h ds:00000000`0130d3d0=40000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0xa: 000007fe`fd845c9a 0f8590090200 jne KERNELBASE!TlsGetValue+0x11c0 (000007fe`fd866630) [br=0] 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x10: 000007fe`fd845ca0 4533c9 xor r9d,r9d 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x13: 000007fe`fd845ca3 48899c24f0000000 mov qword ptr [rsp+0F0h],rbx ss:00000000`0130d2b0={cimwin32!MyCWin32ComputerSystemSet (000007fe`f52a0ea0)} ... 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x16e: 000007fe`fd845dfe 48894b28 mov qword ptr [rbx+28h],rcx ds:00000000`0130d3f8=0000000000000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x172: 000007fe`fd845e02 482b8c2488000000 sub rcx,qword ptr [rsp+88h] ss:00000000`0130d248=00e08d0200000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x17a: 000007fe`fd845e0a 48894b30 mov qword ptr [rbx+30h],rcx ds:00000000`0130d400=0000000000000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x17e: 000007fe`fd845e0e 488bbc24e0000000 mov rdi,qword ptr [rsp+0E0h] ss:00000000`0130d2a0=f01b150000000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x186: 000007fe`fd845e16 488b9c24f0000000 mov rbx,qword ptr [rsp+0F0h] ss:00000000`0130d2b0=d08e150000000000 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x18e: 000007fe`fd845e1e 4881c4e8000000 add rsp,0E8h 0:006> p KERNELBASE!GlobalMemoryStatusEx+0x195: 000007fe`fd845e25 c3 ret 0:006> p cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x32a: 000007fe`f50d677a 413bc4 cmp eax,r12d 0:006> p cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x32d: 000007fe`f50d677d 7418 je cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x347 (000007fe`f50d6797) [br=0] 0:006> p cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x32f: 000007fe`f50d677f 4c8b842428010000 mov r8,qword ptr [rsp+128h] ss:00000000`0130d3d8=00e0385400000000 0:006> p
I have been stepping through the GlobalMemoryStatusEx till the return (ret) command. After that I saw that the memory size has been stored in the register r8 (see line "mov r8,qword ptr [rsp+128h]") and I dumped the value of the registers by simply typing r in the WinDbg command window:
0:006> r rax=0000000000000001 rbx=0000000000158ed0 rcx=000007fffd702000 rdx=00000000966e9000 rsi=0000000000151bf0 rdi=0000000000151bf0 rip=000007fef50d6787 rsp=000000000130d2b0 rbp=000007fef52a0ea0 r8=000000005438e000 r9=fffffffffffffceb r10=0000000000000000 r11=0000000000000286 r12=0000000000000000 r13=0000000000000001 r14=0000000000000003 r15=ffffffffffffffff iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x337: 000007fe`f50d6787 488d15ba5b1400 lea rdx,[cimwin32!`string' (000007fe`f521c348)]
Here we can see that the register r8 contains the value of the memory size 0x000000005438e000 = 1413013504 (decimal) = 1347 MB
At this moment there have been 1347 MB of memory assigned to my virtual machine. But unfortunately the installer asked for 2 GB. Therefore I simply changed the value of the register r8 to 0x0000000080000000 = 2147483648 (decimal) = 2048 MB
r @r8=80000000
Finally, I resumed the process and voila the installer proceeded.