Basic AMD64 System::Call support

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6444 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2014-03-03 18:10:53 +00:00
parent a7261be70c
commit a7076ff238
9 changed files with 268 additions and 46 deletions

View file

@ -26,14 +26,25 @@ docs = Split("""
Import('BuildPlugin env') Import('BuildPlugin env')
if env['TARGET_ARCH'] != 'amd64': defs = ['SYSTEM_EXPORTS']
msvc = 'msvc' in env['TOOLS'] or 'mstoolkit' in env['TOOLS']
if env['TARGET_ARCH'] != 'amd64' or msvc: # BUGBUG: Call-amd64.S is missing GAS macros
srcsuff = ''
if env['TARGET_ARCH'] != 'x86':
srcsuff = '-' + env['TARGET_ARCH']
defs += ['SYSTEM_NOCALLBACKS'] # BUGBUG: Remove this when CallBack() is implemented
if msvc: # BUGBUG: Remove this when GAS is fixed
defs += ['SYSTEM_PARTIALCALLSUPPORT']
filename = 'Call' + srcsuff
conf = env.Configure() conf = env.Configure()
if conf.TryCompile('END', '.S'): if conf.TryCompile('END', '.S'):
files += ['Source/Call.S'] files += ['Source/'+filename+'.S']
elif conf.TryCompile('.end', '.sx'): elif conf.TryCompile('.end', '.sx'):
files += ['Source/Call.sx'] files += ['Source/'+filename+'.sx']
else: else:
print 'WARNING: System.dll: unable to find assembler for Call.S' print 'WARNING: System.dll: unable to find assembler for '+filename+'.S'
conf.Finish() conf.Finish()
else: else:
print 'WARNING: System.dll: missing Win64 code, dynamic function calls not supported' print 'WARNING: System.dll: missing Win64 code, dynamic function calls not supported'
@ -45,7 +56,7 @@ BuildPlugin(
examples, examples,
docs, docs,
nodeflib = False, nodeflib = False,
defines = ['SYSTEM_EXPORTS'] defines = defs
) )
res = 'Resource/Resource.rc' res = 'Resource/Resource.rc'

View file

@ -0,0 +1,181 @@
;#
;# This file is a part of NSIS.
;#
;# Copyright (C) 2014 Anders Kjersem
;#
;# Licensed under the zlib/libpng license (the "License");
;# you may not use this file except in compliance with the License.
;#
;# Licence details can be found in the file COPYING.
;#
;# This software is provided 'as-is', without any express or implied
;# warranty.
;#
;#
;# MASM:
;# ml64.exe /c Call-amd64.S
;#
; .if 0
;# MASM
SECTION_DATA equ .data
SECTION_CODE equ .code
FUNC_DECL MACRO name
name PROC
ENDM
FUNC_END MACRO name
name ENDP
ENDM
;# ~MASM
IF 0
; .else
;# GNU
.intel_syntax noprefix
#define IFDEF .ifdef
#define ELSE .else
#define ENDIF .endif
#define SECTION_DATA .data
#define SECTION_CODE .text
#define END .end
#define EXTERN .extern
;# ~GNU
ENDIF
EXTERN __imp_GetLastError : PROC
IFDEF SYSTEM_LOG_DEBUG
EXTERN __imp_IsDebuggerPresent : PROC
ENDIF
EXTERN LastError : DWORD
EXTERN GetProcOffset : PROC
EXTERN GetParamsOffset : PROC
EXTERN GetSizeOfProcParam : PROC
EXTERN GetValueOffsetParam : PROC
EXTERN SetProcResultOk : PROC
EXTERN GetErrorOption : PROC
SECTION_CODE
FUNC_DECL CallProc2 ;# rcx=SystemProc* edx=ParamCount
mov [rsp+8h], r12
mov [rsp+10h], r13
mov [rsp+18h], r14
;#mov [rsp+20h], r15
;# The stack is unaligned on function entry. We have to calculate the required
;# stack size for our parameters + maybe 8 padding bytes to end up 16 byte aligned.
pSystemProc equ r14
mov pSystemProc, rcx ;# Save SystemProc*
;# Not required since we zero-extend eax: xor rax, rax
mov r13d, edx ;# Save ParamCount
imul eax, edx, 8
and edx, 1
jnz noparamalignpadding
lea eax, [eax+8] ;# sizeof(params) + 8 will make us 16 byte aligned
noparamalignpadding:
cmp eax, 28h ;# The ABI guarantees shadow space for the 4 register parameters
ja computedstacksize
mov eax, 28h ;# Minimum (4*8) + 8 to align
computedstacksize:
mov r12d, eax ;# Save stack size (Zero-extended mov)
sub rsp, r12
IFDEF SYSTEM_LOG_DEBUG
;# BUGBUG: Remove this
call qword ptr [__imp_IsDebuggerPresent]
test eax, eax
jz nodbgbrk
int 3
nodbgbrk:
ENDIF
;# We are going to set all stack parameters including the first 4,
;# it does not hurt to do that and it allows us to copy them to
;# their registers without reading pSystemProc->Params[1..3] again
call GetSizeOfProcParam
mov r9, rax ;# Store sizeof(ProcParameter)
call GetValueOffsetParam
mov r8, rax ;# Store FIELD_OFFSET(ProcParameter,Value)
call GetParamsOffset
lea r10, [pSystemProc+rax] ;# Store pSystemProc+FIELD_OFFSET(SystemProc,Params)
mov ecx, r13d ;# Zero-extended mov
test rcx, rcx
jz callthefunc
setparameter:
mov rax, r9
mul rcx ;# rax = sizeof(ProcParameter) * paramidx (paramidx is 1 based because the return value is stored in Params[0])
add rax, r10 ;# rax += pSystemProc->Params
mov rax, qword ptr [rax+r8] ;# rax = pSystemProc->Params[paramidx].Value
dec rcx
mov [rsp+(8*rcx)], rax
inc rcx
loop setparameter
;# The 4 parameter registers are all volatile so we might as well assign all of them:
;# setparam4:
;# cmp r13d, 4
;# jb setparam3
mov r9, [rsp+(8*3)]
;# setparam3:
;# cmp r13d, 3
;# jb setparam2
mov r8, [rsp+(8*2)]
;# setparam2:
;# cmp r13d, 2
;# jb setparam1
mov rdx, [rsp+(8*1)]
;# setparam1:
;# cmp r13d, 1
;# jb callthefunc
mov rcx, [rsp+(8*0)]
callthefunc:
call GetProcOffset
mov r10, qword ptr [pSystemProc+rax]
xor rax, rax ;# Fix bug #1535007
call r10
mov r13, rax ;# Save return value
mov rcx, pSystemProc
call GetErrorOption
test eax, eax
jz capturegle_done
call qword ptr [__imp_GetLastError]
mov dword ptr [LastError], eax
capturegle_done:
;# proc->Params[0].Value = pSystemProc->Proc's return value
call GetParamsOffset
mov rdx, rax ;# This assumes that the next function is not going to clobber rdx!
call GetValueOffsetParam
add rdx, rax
mov qword ptr [pSystemProc+rdx], r13
mov rcx, pSystemProc
call SetProcResultOk ;# BUGBUG: This is pointless, system.c should just assume we are OK
mov rax, pSystemProc ;# Return SystemProc*
;# Epilog:
;# http://msdn.microsoft.com/en-us/library/tawsa7cb claims that only
;# add/lea rsp and pop is valid in the epilog. Unwind might fail on our version?
add rsp, r12 ;# Restore stack
;# Restore nonvolatile registers:
mov r12, [rsp+8h]
mov r13, [rsp+10h]
mov r14, [rsp+18h]
;#mov r15, [rsp+20h]
ret
FUNC_END CallProc2
END

View file

@ -275,6 +275,7 @@ TODO: CallProc/Back not implemeted.
Fake the behavior of the System plugin for the LoadImage API function so MUI works. Fake the behavior of the System plugin for the LoadImage API function so MUI works.
BUGBUG: MUI is leaking DeleteObject and failing GetClientRect BUGBUG: MUI is leaking DeleteObject and failing GetClientRect
*/ */
#ifndef SYSTEM_PARTIALCALLSUPPORT
SystemProc* CallProc(SystemProc *proc) SystemProc* CallProc(SystemProc *proc)
{ {
INT_PTR ret, *place; INT_PTR ret, *place;
@ -294,12 +295,13 @@ SystemProc* CallProc(SystemProc *proc)
if (place) *place = ret; if (place) *place = ret;
return proc; return proc;
} }
#endif // ~SYSTEM_PARTIALCALLSUPPORT
SystemProc* CallBack(SystemProc *proc) SystemProc* CallBack(SystemProc *proc)
{ {
proc->ProcResult = PR_ERROR; proc->ProcResult = PR_ERROR;
return proc; return proc;
} }
#endif #endif // ~_WIN64
PLUGINFUNCTION(Call) PLUGINFUNCTION(Call)
@ -355,7 +357,7 @@ PLUGINFUNCTION(Call)
proc->Params[0] = pp; // Restore old return param proc->Params[0] = pp; // Restore old return param
} }
else else
ParamsOut(proc); ParamsOut(proc);
} }
if (proc->ProcResult != PR_CALLBACK) if (proc->ProcResult != PR_CALLBACK)
@ -768,7 +770,9 @@ SystemProc *PrepareProc(BOOL NeedForCall)
break; break;
case _T('!'): temp = -temp; break; case _T('!'): temp = -temp; break;
case _T('c'): case _T('c'):
#ifndef _WIN64
temp2 = POPT_CDECL; temp2 = POPT_CDECL;
#endif
break; break;
case _T('r'): case _T('r'):
temp2 = POPT_ALWRETURN; temp2 = POPT_ALWRETURN;
@ -993,16 +997,19 @@ void ParamsIn(SystemProc *proc)
#ifdef SYSTEM_LOG_DEBUG #ifdef SYSTEM_LOG_DEBUG
{ {
TCHAR buf[666]; TCHAR buf[666];
wsprintf(buf, _T("\t\t\tParam In %d: type %d value ")SYSFMT_HEXPTR _T(" value2 0x%08X"), i, UINT32 hi32 = 0;
par->Type, par->Value, par->_value); #ifndef _WIN64
hi32 = par->_value;
#endif
wsprintf(buf, _T("\t\t\tParam In %d:\tType=%d Value=")SYSFMT_HEXPTR _T(" hi32=0x%08X"), i,
par->Type, par->Value, hi32);
SYSTEM_LOG_ADD(buf); SYSTEM_LOG_ADD(buf);
SYSTEM_LOG_POST; SYSTEM_LOG_POST;
} }
#endif #endif
if (i == 0) break; if (i == 0) break;
if (i == proc->ParamCount) i = 0; if (i == proc->ParamCount) i = 0; else i++;
else i++;
} }
} }
@ -1101,7 +1108,7 @@ void ParamsOut(SystemProc *proc)
#ifdef SYSTEM_LOG_DEBUG #ifdef SYSTEM_LOG_DEBUG
{ {
TCHAR dbgbuf[99]; TCHAR dbgbuf[99];
wsprintf(dbgbuf, _T(") %d:\tType=%d Optn=%d Size=%d Data="), wsprintf(dbgbuf, _T(")\t%d:\tType=%d Optn=%d Size=%d Data="),
i, proc->Params[i].Type, proc->Params[i].Option, proc->Params[i].Size); i, proc->Params[i].Type, proc->Params[i].Option, proc->Params[i].Size);
SYSTEM_LOG_ADD(dbgbuf); SYSTEM_LOG_ADD(dbgbuf);
SYSTEM_LOG_ADD(realbuf); SYSTEM_LOG_ADD(realbuf);
@ -1118,7 +1125,7 @@ void ParamsOut(SystemProc *proc)
HANDLE CreateCallback(SystemProc *cbproc) HANDLE CreateCallback(SystemProc *cbproc)
{ {
#ifdef SYSTEM_X64 #ifdef SYSTEM_AMD64
return BUGBUG64(HANDLE) NULL; return BUGBUG64(HANDLE) NULL;
#else #else
char *mem; char *mem;
@ -1285,7 +1292,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)
#ifdef SYSTEM_X86 #ifdef SYSTEM_X86
retexpr[0] = (char) 0xC2; retexpr[0] = (char) 0xC2;
retexpr[2] = 0x00; retexpr[2] = 0x00;
#elif defined(SYSTEM_X64) #elif defined(SYSTEM_AMD64)
retexpr[0] = BUGBUG64(0); retexpr[0] = BUGBUG64(0);
#else #else
#error TODO #error TODO
@ -1329,9 +1336,9 @@ unsigned int GetErrorOption(SystemProc *proc)
/* /*
Returns offset for element Proc of SystemProc structure Returns offset for element Proc of SystemProc structure
*/ */
unsigned int GetProcOffset(void) UINT_PTR GetProcOffset(void)
{ {
return (unsigned int)(&(((SystemProc *)0)->Proc)); return (UINT_PTR)(&(((SystemProc *)0)->Proc));
} }
/* /*
@ -1369,15 +1376,15 @@ unsigned int GetParamCount(SystemProc *proc)
/* /*
Returns offset for element Params of SystemProc structure Returns offset for element Params of SystemProc structure
*/ */
unsigned int GetParamsOffset(void) UINT_PTR GetParamsOffset(void)
{ {
return (unsigned int)(&(((SystemProc *)0)->Params)); return (UINT_PTR)(&(((SystemProc *)0)->Params));
} }
/* /*
Returns size of ProcParameter structure Returns size of ProcParameter structure
*/ */
unsigned int GetSizeOfProcParam(void) UINT_PTR GetSizeOfProcParam(void)
{ {
return (sizeof(ProcParameter)); return (sizeof(ProcParameter));
} }
@ -1393,11 +1400,12 @@ unsigned int GetSizeOffsetParam(void)
/* /*
Returns offset for element Value of ProcParameter structure Returns offset for element Value of ProcParameter structure
*/ */
unsigned int GetValueOffsetParam(void) UINT_PTR GetValueOffsetParam(void)
{ {
return (unsigned int)(&(((ProcParameter *)0)->Value)); return (UINT_PTR)(&(((ProcParameter *)0)->Value));
} }
#ifndef _WIN64
/* /*
Returns offset for element _value of ProcParameter structure Returns offset for element _value of ProcParameter structure
*/ */
@ -1405,6 +1413,7 @@ unsigned int Get_valueOffsetParam(void)
{ {
return (unsigned int)(&(((ProcParameter *)0)->_value)); return (unsigned int)(&(((ProcParameter *)0)->_value));
} }
#endif
/* /*
Sets "CLONE" option Sets "CLONE" option

View file

@ -4,16 +4,17 @@
// This should probably be moved to platform.h at some point // This should probably be moved to platform.h at some point
#if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__) #if defined(_M_X64) || defined(_M_AMD64) || defined(__amd64__)
# define SYSTEM_X64 # define SYSTEM_AMD64
#elif defined(_M_IX86) || defined(__i386__) || defined(_X86_) #elif defined(_M_IX86) || defined(__i386__) || defined(_X86_)
# define SYSTEM_X86 # define SYSTEM_X86
#else #else
# error "Unknown architecture!" # error "Unknown architecture!"
#endif #endif
#ifdef _WIN64 #ifdef _WIN64
#define SYSFMT_HEXPTR _T("0x%016IX") # define SYSFMT_HEXPTR _T("0x%016IX")
#else #else
#define SYSFMT_HEXPTR _T("0x%08X") # define SYSFMT_HEXPTR _T("0x%08X")
#endif #endif
@ -25,9 +26,9 @@
// defined with this macro as being exported. // defined with this macro as being exported.
#ifdef SYSTEM_EXPORTS #ifdef SYSTEM_EXPORTS
#define SYSTEM_API __declspec(dllexport) # define SYSTEM_API __declspec(dllexport)
#else #else
#define SYSTEM_API __declspec(dllimport) # define SYSTEM_API __declspec(dllimport) // BUGBUG: This is a plugin, who is going to import the functions directly?
#endif #endif
#define NEW_STACK_SIZE 256*256 #define NEW_STACK_SIZE 256*256
@ -123,7 +124,7 @@ struct tag_CallbackThunk
#pragma pack(pop) #pragma pack(pop)
*/ */
char asm_code[10]; char asm_code[10];
#elif defined(SYSTEM_X64) #elif defined(SYSTEM_AMD64)
char asm_code[BUGBUG64(1)]; // TODO: BUGBUG64 char asm_code[BUGBUG64(1)]; // TODO: BUGBUG64
#else #else
#error "Asm thunk not implemeted for this architecture!" #error "Asm thunk not implemeted for this architecture!"
@ -135,7 +136,7 @@ struct tag_CallbackThunk
// Free() only knows about pNext in CallbackThunk, it does not know anything about the assembly, that is where this helper comes in... // Free() only knows about pNext in CallbackThunk, it does not know anything about the assembly, that is where this helper comes in...
#ifdef SYSTEM_X86 #ifdef SYSTEM_X86
# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) ( (SystemProc*) *(unsigned int*) (((char*)(pCbT))+1) ) # define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) ( (SystemProc*) *(unsigned int*) (((char*)(pCbT))+1) )
#elif defined(SYSTEM_X64) #elif defined(SYSTEM_AMD64)
# define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) BUGBUG64(NULL) # define GetAssociatedSysProcFromCallbackThunkPtr(pCbT) BUGBUG64(NULL)
#else #else
# error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!" # error "GetAssociatedSysProcFromCallbackThunkPtr not defined for the current architecture!"
@ -145,14 +146,23 @@ struct tag_CallbackThunk
extern const int ParamSizeByType[]; // Size of every parameter type (*4 bytes) extern const int ParamSizeByType[]; // Size of every parameter type (*4 bytes)
extern HANDLE CreateCallback(SystemProc *cbproc); extern HANDLE CreateCallback(SystemProc *cbproc);
extern SystemProc *PrepareProc(BOOL NeedForCall); extern SystemProc* PrepareProc(BOOL NeedForCall);
extern void ParamAllocate(SystemProc *proc); extern void ParamAllocate(SystemProc *proc);
extern void ParamsDeAllocate(SystemProc *proc); extern void ParamsDeAllocate(SystemProc *proc);
extern void ParamsIn(SystemProc *proc); extern void ParamsIn(SystemProc *proc);
extern void ParamsOut(SystemProc *proc); extern void ParamsOut(SystemProc *proc);
extern SystemProc *CallProc(SystemProc *proc); #ifdef SYSTEM_AMD64
extern SystemProc *CallBack(SystemProc *proc); #ifdef SYSTEM_PARTIALCALLSUPPORT
extern SystemProc *RealCallBack(); extern SystemProc* CallProc2(SystemProc *proc, UINT_PTR ParamCount);
#define CallProc(p) CallProc2((p), (p)->ParamCount) // ParamCount is passed as a parameter so CallProc2 can determine the required stack size without a function call
#endif
#else // !SYSTEM_AMD64
extern SystemProc* CallProc(SystemProc *proc);
#endif // ~SYSTEM_AMD64
#ifndef SYSTEM_NOCALLBACKS
extern SystemProc* CallBack(SystemProc *proc);
extern SystemProc* RealCallBack();
#endif
extern void CallStruct(SystemProc *proc); extern void CallStruct(SystemProc *proc);
#ifdef _UNICODE #ifdef _UNICODE

View file

@ -422,7 +422,7 @@ System::Free $0
<blockquote> <blockquote>
<ul> <ul>
<li>To find out the index of a member in a COM interface, you need to search for the definition of this COM interface in the header files that come with Visual C/C++ or the Platform SDK. Remember the index is zero based.</li> <li>To find out the index of a member in a COM interface, you need to search for the definition of this COM interface in the header files that come with Visual C/C++ or the Platform SDK. Remember the index is zero based.</li>
<li>If a function can't be found, an `A' will be appended to its name and it will be looked up again. This is done because a lot of Windows API functions have two versions, one for ANSI strings and one for Unicode strings. The ANSI version of the function is marked with `A' and the Unicode version is marked with `W'. For example: lstrcpyA and lstrcpyW.</li> <li>If a function can't be found or the <code>t</code> parameter type was used, an `A' or `W' will be appended to its name and it will be looked up again. This is done because a lot of Windows API functions have two versions, one for ANSI strings and one for Unicode strings. The ANSI version of the function is marked with `A' and the Unicode version is marked with `W'. For example: lstrcpyA and lstrcpyW.</li>
</ul> </ul>
</blockquote> </blockquote>
@ -436,7 +436,7 @@ System::Free $0
</tr> </tr>
<tr> <tr>
<th>c</th> <th>c</th>
<td>cdecl calling convention (the stack restored by caller). By default stdcall calling convention is used (the stack restored by callee).</td> <td>cdecl calling convention (the stack restored by caller). By default stdcall calling convention is used on x86 (the stack restored by callee).</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>

View file

@ -6,6 +6,12 @@ Released on ?, 2014
\S1{v3.0b0-rl} Release Notes \S1{v3.0b0-rl} Release Notes
\S1{v3.0b0-cl} Changelog
\S2{} Major Changes
\b Basic AMD64 System::Call support
\S2{} Minor Changes \S2{} Minor Changes
\b Added Int<32|64|Ptr><Op|Cmp[U]> helper macros to Util.nsh \b Added Int<32|64|Ptr><Op|Cmp[U]> helper macros to Util.nsh

View file

@ -45,7 +45,8 @@ defenv.Append(CPPDEFINES = [('NSISCALL', '$STDCALL')])
### asm ### asm
defenv.Append(ASFLAGS = ['/coff']) if 'x86' in defenv.get('TARGET_ARCH','x86'):
defenv.Append(ASFLAGS = ['/coff']) # ML64 does not support /coff
### debug ### debug

View file

@ -287,9 +287,10 @@ def generate(env):
include_path, lib_path, exe_path, sdk_path = "", "", "", "" include_path, lib_path, exe_path, sdk_path = "", "", "", ""
targ_arc = env.get('TARGET_ARCH', 'x86')
if os.environ.has_key('MSVC_USE_SCRIPT') and "None" == os.environ['MSVC_USE_SCRIPT']: if os.environ.has_key('MSVC_USE_SCRIPT') and "None" == os.environ['MSVC_USE_SCRIPT']:
for x in ['INCLUDE', 'LIB', 'PATH']: env['ENV'][x] = "" for x in ['INCLUDE', 'LIB', 'PATH', 'CL', 'LINK', 'ML']: env['ENV'][x] = ""
if not env.WhereIs('cl', os.environ['PATH']): if not env.WhereIs('cl', os.environ['PATH']):
raise SCons.Errors.InternalError("CL not found in %s" % os.environ['PATH']) raise SCons.Errors.InternalError("CL not found in %s" % os.environ['PATH'])
include_path = os.environ['INCLUDE'] include_path = os.environ['INCLUDE']
@ -309,8 +310,8 @@ def generate(env):
env.PrependENVPath('INCLUDE', include_path) env.PrependENVPath('INCLUDE', include_path)
env.PrependENVPath('LIB', lib_path) env.PrependENVPath('LIB', lib_path)
env.PrependENVPath('PATH', exe_path) env.PrependENVPath('PATH', exe_path)
env['ENV']['CPU'] = 'i386' # TODO: Check TARGET_ARCH for AMD64 env['ENV']['CPU'] = (targ_arc.upper(), 'i386')['x86' in targ_arc.lower()] # i386 or AMD64
env['ENV']['TARGETOS'] = 'BOTH' env['ENV']['TARGETOS'] = 'BOTH'
env['ENV']['APPVER'] = '4.0' env['ENV']['APPVER'] = '4.0'
env['ENV']['MSSDK'] = sdk_path env['ENV']['MSSDK'] = sdk_path
@ -319,7 +320,7 @@ def generate(env):
env['ENV']['INETSDK'] = sdk_path env['ENV']['INETSDK'] = sdk_path
env['ENV']['MSSDK'] = sdk_path env['ENV']['MSSDK'] = sdk_path
env['ENV']['MSTOOLS'] = sdk_path env['ENV']['MSTOOLS'] = sdk_path
env['CFILESUFFIX'] = '.c' env['CFILESUFFIX'] = '.c'
env['CXXFILESUFFIX'] = '.cc' env['CXXFILESUFFIX'] = '.cc'
@ -329,7 +330,10 @@ def generate(env):
env['AR'] = '"' + sdk_path_AR + '"' env['AR'] = '"' + sdk_path_AR + '"'
env['ARFLAGS'] = SCons.Util.CLVar('/nologo') env['ARFLAGS'] = SCons.Util.CLVar('/nologo')
env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}" env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
if 'AMD64' in targ_arc.upper():
env['AS'] = 'ml64'
env['SHLINK'] = '$LINK' env['SHLINK'] = '$LINK'
env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll') env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
env['_SHLINK_TARGETS'] = win32ShlinkTargets env['_SHLINK_TARGETS'] = win32ShlinkTargets

View file

@ -1056,11 +1056,11 @@ static INT_PTR CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l
{ {
BOOL (WINAPI *GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = BOOL (WINAPI *GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) =
#ifdef _WIN64 #ifdef _WIN64
GetDiskFreeSpaceEx; GetDiskFreeSpaceEx;
#else #else
myGetProcAddress(MGA_GetDiskFreeSpaceEx); myGetProcAddress(MGA_GetDiskFreeSpaceEx);
#endif
if (GDFSE) if (GDFSE)
#endif
{ {
ULARGE_INTEGER available64; ULARGE_INTEGER available64;
ULARGE_INTEGER a, b; ULARGE_INTEGER a, b;
@ -1093,7 +1093,7 @@ static INT_PTR CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l
} }
} }
if (!available_set) // TODO: Can GetDiskFreeSpace succeed when ..Ex failed on x64? if (!available_set && sizeof(void*) <= 4)
{ {
DWORD spc, bps, fc, tc; DWORD spc, bps, fc, tc;
TCHAR *root; TCHAR *root;