December 16, 2013
Am Mon, 16 Dec 2013 08:19:40 -0500
schrieb Hugo Florentino <hugo@acdam.cu>:

> So currently D has no specific function for detecting the OS architecture at runtime? I had not expected this.

You are the first to raise this question. I guess most of us just install either a 32-bit version or a 64-bit version and never found a need to ask from inside the running program if it is actually the correct architecture. Your launcher use-case stands out.

But there is really more to it than 32 or 64. There is also x32, which is a mix of 32-bit pointers with 64-bit CPU features, giving the best overall performance. Also, while dmd only emits x86 code, the language and the standard library strive to be architecture independent except for some minimal requirements for data types or thread local storage.

And a function like that should probably return an array of supported ABIs, like [amd64, x32, x86] with the "main" or most feature rich architecture in index 0. Just my 2ยข

-- 
Marco

December 16, 2013
On 2013-12-16 11:53, Hugo Florentino wrote:
> Hi,
>
> I am writing a launcher to make a Windows application portable, but
> since this application supports both x86 and x86_64, I would like to
> detect the architecture of the OS my launcher is being run on, in order
> to launch the proper executable.

The easiest would be: if you launcher is built for 64bit, pick the 64bit application, otherwise pick the 32bit application.

-- 
/Jacob Carlborg
December 16, 2013
On Monday, 16 December 2013 at 13:19:52 UTC, Hugo Florentino wrote:
> On Mon, 16 Dec 2013 12:59:52 +0100, John Colvin wrote:
>> On Monday, 16 December 2013 at 11:56:07 UTC, Hugo Florentino wrote:
>>> On Mon, 16 Dec 2013 12:40:17 +0100, MrSmith wrote:
>>>> I think this is what he want
>>>> http://dlang.org/phobos/core_cpuid.html#.isX86_64
>>>
>>> Thanks, that's precisely what I needed :)
>>
>> Are you sure?
>>
>> This will tell you about the processor, but not necessarily about
>> what the OS supports. I don't know, but you may find that when using
>> windows 32bit on an x64 machine, cpuid will tell you the cpu is 64bit,
>> but the OS won't let you run any 64bit code.
>
> You are right. I realized that this function was not quite what I needed when running this code on a 32 bit system:
>
> import std.stdio, core.cpuid;
>
> int main() {
>   immutable auto appname = "myapp";
>   auto appversion = !isX86_64() ? appname ~ "32" : appname ~ "64") ~ ".exe";
>   scope(failure) return -1;
>   writeln(appversion);
>   return 0;
> }
>
> I was expecting "myapp32.exe" but got "myapp64.exe". Apparently what isX86_64() detects is the capability of the processor, not the arquitecture of the OS.
>
> So currently D has no specific function for detecting the OS architecture at runtime? I had not expected this.
>
> I will try using the other options though. Thanks

Try building the launcher as a 32bit executable then use the following code:

import std.stdio;
import core.sys.windows.windows;

enum AMD64   = 9;
enum IA64    = 6;
enum X86     = 0;
enum UNKNOWN = 0xFFFF;

void main()
{
	SYSTEM_INFO executableEnvironment;
	SYSTEM_INFO outerEnvironment;

	GetSystemInfo(&executableEnvironment);
	GetNativeSystemInfo(&outerEnvironment);

	// See the above enums for values.
	writefln("Executable: %s", executableEnvironment.wProcessorArchitecture);
	writefln("Outer: %s", outerEnvironment.wProcessorArchitecture);
}

If the launcher is running under Wow64 (the 32bit emulation layer on a 64bit processor) the results will be different for executableEnvironment and outerEnvironment. GetSystemInfo gets the environment the executable is running under, GetNativeSystemInfo gets the 'real' environment. I guess it's a place to start?
December 16, 2013
Am Mon, 16 Dec 2013 16:04:07 +0100
schrieb Jacob Carlborg <doob@me.com>:

> On 2013-12-16 11:53, Hugo Florentino wrote:
> > Hi,
> >
> > I am writing a launcher to make a Windows application portable, but since this application supports both x86 and x86_64, I would like to detect the architecture of the OS my launcher is being run on, in order to launch the proper executable.
> 
> The easiest would be: if you launcher is built for 64bit, pick the 64bit application, otherwise pick the 32bit application.

Hehe, I guess the whole purpose of the launcher is to run in
32-bit and detect at runtime if the 64-bit main executable can
be run or the 32-bit version must be used.

-- 
Marco

December 16, 2013
On Mon, 16 Dec 2013 10:53:45 -0000, Hugo Florentino <hugo@acdam.cu> wrote:
> I am writing a launcher to make a Windows application portable, but since this application supports both x86 and x86_64, I would like to detect the architecture of the OS my launcher is being run on, in order to launch the proper executable.
>
> How can I do this?

Compile the launcher as 32bit, and use this global boolean "isWow64":

import std.stdio;
import std.internal.windows.advapi32;

void main(string[] args)
{
  writefln(isWow64 ? "yes" : "no");
}

You can thank Kenji for this one :)  Someone document this somewhere please :p

The code from advapi32 for those interested..

immutable bool isWow64;

shared static this()
{
    // WOW64 is the x86 emulator that allows 32-bit Windows-based applications to run seamlessly on 64-bit Windows
    // IsWow64Process Function - Minimum supported client - Windows Vista, Windows XP with SP2
    alias extern(Windows) BOOL function(HANDLE, PBOOL) fptr_t;
    auto hKernel = GetModuleHandleA("kernel32");
    auto IsWow64Process = cast(fptr_t) GetProcAddress(hKernel, "IsWow64Process");
    BOOL bIsWow64;
    isWow64 = IsWow64Process && IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64;
}

Basically, your 32 bit launcher process has to, at runtime, ask Kernel32 for a function "IsWow64Process" which only exists on 64 bit windows.  So, if it doesn't find it, it's 32 bit.  If it finds it, it calls it with the current PID to find out of the current process is a 32 bit app running inside WOW64 (the emulator layer) and that gives you the answer.

R


-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
December 16, 2013
On 2013-12-16 17:46, Marco Leise wrote:

> Hehe, I guess the whole purpose of the launcher is to run in
> 32-bit and detect at runtime if the 64-bit main executable can
> be run or the 32-bit version must be used.

The only advantage of that is that only a 32bit launcher needs to be distributed. Perhaps that's the whole idea.

-- 
/Jacob Carlborg
December 16, 2013
GetNativeSystemInfo worked. Thanks!

The code ended being like this (it seems to be working both in x86 and x86_64):

import std.file: exists, getcwd;
import std.path: buildPath, dirName;
import std.string: format, toStringz;
import core.sys.windows.windows;

enum X86   = 0;
enum AMD64 = 9;
immutable static auto appname = "myapp";

extern(Windows) HANDLE ShellExecuteA(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, int);
extern(Windows) int MessageBoxA(HWND, LPCSTR, LPCSTR, UINT);

int main() {
  auto appath = getcwd();
  string appexe;
  SYSTEM_INFO env;
  GetNativeSystemInfo(&env);
  switch(env.wProcessorArchitecture) {
    case X86: appexe = buildPath(appath, appname ~ "32.exe"); break;
    case AMD64: appexe = buildPath(appath, appname ~ "64.exe"); break;
    default:
      MessageBoxA(null, "System architecture is not supported.", "Error", MB_ICONHAND + MB_OK);
      return -1;
  }
  if (exists(appexe)) {
    auto param = format(`/ini="%s"`, buildPath(appath, appname ~ ".ini"));
    ShellExecuteA(null, "", toStringz(appexe), toStringz(param), "", SW_SHOWMAXIMIZED);
    scope(failure) return -2;
  }
  return 0;
}
December 16, 2013
On Mon, 16 Dec 2013 17:04:18 -0000, Regan Heath wrote:
> ...
> Compile the launcher as 32bit, and use this global boolean "isWow64":
> ...

Thanks, it's nice to have another option.
What do you guys think are the possible advantages/disadvantages of either solution?

December 17, 2013
On Mon, 16 Dec 2013 21:26:31 -0000, Hugo Florentino <hugo@acdam.cu> wrote:

> On Mon, 16 Dec 2013 17:04:18 -0000, Regan Heath wrote:
>> ...
>> Compile the launcher as 32bit, and use this global boolean "isWow64":
>> ...
>
> Thanks, it's nice to have another option.
> What do you guys think are the possible advantages/disadvantages of either solution?

Is GetNativeSystemInfo your other solution?  On the MSDN page for GetNativeSystemInfo it recommends using IsWow64Process to detect if you're running under WOW64, at which point you would then call GetNativeSystemInfo.

I am not sure what GetNativeSystemInfo does if called from a 32 bit exe on a 32 bit OS..

I /know/ that the code in std.internal.windows.advapi32 which dynamically loads and calls IsWow64Process will work, because we use it here at work for this very purpose.  It's also the simplest most direct way to answer this specific question and it's already present, tested and working in phobos .. so I would be inclined to use it, in preference over GetNativeSystemInfo.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
December 17, 2013
On Mon, 16 Dec 2013 21:27:13 -0000, Hugo Florentino <hugo@acdam.cu> wrote:

> On Mon, 16 Dec 2013 20:23:00 +0100, Jacob Carlborg wrote:
>> On 2013-12-16 17:46, Marco Leise wrote:
>>
>>> Hehe, I guess the whole purpose of the launcher is to run in
>>> 32-bit and detect at runtime if the 64-bit main executable can
>>> be run or the 32-bit version must be used.
>>
>> The only advantage of that is that only a 32bit launcher needs to be
>> distributed. Perhaps that's the whole idea.
>
> It is. :)

"Process Explorer" by sysinternals, now distributed by M$ does something similar.
http://technet.microsoft.com/en-gb/sysinternals/bb896653.aspx

It is a 32 bit exe, which detects the OS bit width and if it's 64 bit extracts a 64 exe from within itself to run.  When you quit that 64 bit exe, it deletes the file it extracted from disk.  It's quite a neat solution.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/