Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.

Commit 3ba7253

Browse files
Arnaud DiederenArnaud Diederen
authored andcommitted
Backported fixes
1 parent bf7a817 commit 3ba7253

6 files changed

Lines changed: 125 additions & 8 deletions

File tree

idapyswitch.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//lint -esym(1788, iinc) is referenced only by its constructor or destructor
1717

1818
#include <pro.h>
19+
#include <err.h>
1920
#include <fpro.h>
2021
#include <prodir.h>
2122
#include <diskio.hpp>

idapyswitch_win.cpp

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,94 @@ static bool extract_version_from_path(
9797
return true;
9898
}
9999

100+
101+
#pragma comment(lib, "version.lib")
102+
//-------------------------------------------------------------------------
103+
DWORD GetFileVersionNumber(const char *filename, DWORD *pdwMSVer, DWORD *pdwLSVer)
104+
{
105+
DWORD dwResult = NOERROR;
106+
unsigned uiSize;
107+
DWORD dwVerInfoSize;
108+
DWORD dwHandle;
109+
PBYTE prgbVersionInfo = NULL;
110+
VS_FIXEDFILEINFO *lpVSFixedFileInfo = NULL;
111+
112+
DWORD dwMSVer = 0xffffffff;
113+
DWORD dwLSVer = 0xffffffff;
114+
115+
qwstring wfilename;
116+
if ( !utf8_utf16(&wfilename, filename) )
117+
{
118+
dwResult = ERROR_INVALID_PARAMETER;
119+
goto Finish;
120+
}
121+
122+
dwVerInfoSize = GetFileVersionInfoSizeW(wfilename.c_str(), &dwHandle);
123+
if ( dwVerInfoSize != 0 )
124+
{
125+
prgbVersionInfo = (PBYTE)qalloc(dwVerInfoSize);
126+
if ( prgbVersionInfo == NULL )
127+
{
128+
dwResult = ERROR_NOT_ENOUGH_MEMORY;
129+
goto Finish;
130+
}
131+
132+
// Read version stamping info
133+
if ( GetFileVersionInfoW(wfilename.c_str(), dwHandle, dwVerInfoSize, prgbVersionInfo) )
134+
{
135+
// get the value for VS_FIXEDFILEINFO
136+
if ( VerQueryValueW(prgbVersionInfo, L"\\", (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize != 0) )
137+
{
138+
dwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
139+
dwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
140+
}
141+
}
142+
else
143+
{
144+
dwResult = GetLastError();
145+
goto Finish;
146+
}
147+
}
148+
else
149+
{
150+
dwResult = GetLastError();
151+
}
152+
153+
out_verb("%s is version %d.%d.%d.%d\n", filename, HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer));
154+
155+
Finish:
156+
if ( prgbVersionInfo != NULL )
157+
qfree(prgbVersionInfo);
158+
if ( pdwMSVer != NULL )
159+
*pdwMSVer = dwMSVer;
160+
if ( pdwLSVer != NULL )
161+
*pdwLSVer = dwLSVer;
162+
163+
return dwResult;
164+
}
165+
//-------------------------------------------------------------------------
166+
static bool extract_version_from_dll(
167+
pylib_version_t *out,
168+
const char *fname)
169+
{
170+
DWORD dwMSVer, dwLSVer;
171+
DWORD res = GetFileVersionNumber(fname, &dwMSVer, &dwLSVer);
172+
if ( res == NOERROR )
173+
{
174+
out->raw.sprnt("%d.%d.%d.%d", HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer));
175+
// Python DLL versions look like 3.7.4150.1013 -> 3.7.4
176+
out->major = HIWORD(dwMSVer);
177+
out->minor = LOWORD(dwMSVer);
178+
out->revision = HIWORD(dwLSVer) / 1000;
179+
return true;
180+
}
181+
else
182+
{
183+
out_verb("error getting version of \"%s\": %s\n", fname, winerr(res));
184+
return false;
185+
}
186+
}
187+
100188
//-------------------------------------------------------------------------
101189
static bool is_python3Y_dll_file_name(const char *fname)
102190
{
@@ -138,6 +226,9 @@ static bool probe_python_install_dir_from_dll_path(
138226
{
139227
char dll_path[QMAXPATH];
140228
qmakepath(dll_path, sizeof(dll_path), dir, fb.ff_name, nullptr);
229+
pylib_version_t tmp;
230+
if ( extract_version_from_dll(&tmp, path) )
231+
*out_version = tmp;
141232
out_verb("Found: \"%s\" (version: %s)\n", dll_path, out_version->str(&verbuf));
142233
out_paths->push_back(dll_path);
143234

@@ -392,10 +483,24 @@ void pyver_tool_t::do_find_python_libs(pylib_entries_t *result) const
392483
out("IDA previously used: \"%s\" (guessed version: %s). "
393484
"Making this the preferred version.\n",
394485
existing.c_str(), version.str(&verbuf));
395-
pylib_entry_t e(version);
396-
e.paths.swap(paths);
397-
e.preferred = true;
398-
result->entries.push_back(e);
486+
// do we have it in the list?
487+
bool found = false;
488+
for ( pylib_entry_t &e : result->entries )
489+
{
490+
if ( e.paths.has(existing) )
491+
{
492+
found = true;
493+
e.preferred = true;
494+
}
495+
}
496+
if ( !found )
497+
{
498+
// add a new one
499+
pylib_entry_t e(version);
500+
e.paths.swap(paths);
501+
e.preferred = true;
502+
result->entries.push_back(e);
503+
}
399504
}
400505
else
401506
{

idapython.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ static bool return_python_result(
840840
// We use the Python function to execute the script because it knows how to deal with
841841
// module reloading.
842842
static bool IDAPython_ExecFile(
843-
const char *FileName,
843+
const char *path,
844844
PyObject *globals,
845845
qstring *errbuf,
846846
const char *idaapi_script = S_IDAAPI_EXECSCRIPT,
@@ -856,12 +856,22 @@ static bool IDAPython_ExecFile(
856856
}
857857

858858
char script[MAXSTR];
859-
qstrncpy(script, FileName, sizeof(script));
859+
qstrncpy(script, path, sizeof(script));
860860
strrpl(script, '\\', '/');
861+
newref_t py_script(IDAPyStr_FromUTF8(script));
861862

862863
if ( globals == NULL )
863864
globals = get_module_globals();
864-
newref_t py_script(IDAPyStr_FromUTF8(script));
865+
if ( globals != get_module_globals() )
866+
{
867+
// Executions that take place in the scope of their own module,
868+
// should have the '__file__' attribute properly set (so that
869+
// it doesn't just get temporarily set and then removed by
870+
// `ida_idaapi.IDAPython_ExecScript`.
871+
newref_t py_file_key(IDAPyStr_FromUTF8(S_FILE));
872+
if ( !PyDict_Contains(globals, py_file_key.o) )
873+
PyDict_SetItem(globals, py_file_key.o, py_script.o);
874+
}
865875
borref_t py_false(Py_False);
866876
newref_t py_ret(PyObject_CallFunctionObjArgs(
867877
py_execscript.o,
0 Bytes
Binary file not shown.

python/idc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5106,7 +5106,7 @@ def SetType(ea, newtype):
51065106
51075107
@return: 1-ok, 0-failed.
51085108
"""
5109-
if newtype is not '':
5109+
if newtype != '':
51105110
pt = parse_decl(newtype, PT_SIL)
51115111
if pt is None:
51125112
# parsing failed

pywraps.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ static const char S_M_TITLE[] = "_title";
130130
static const char S_CLINK_NAME[] = "__clink__";
131131
static const char S_ON_VIEW_MOUSE_MOVED[] = "OnViewMouseMoved";
132132
static const char S_MAIN[] = "__main__";
133+
static const char S_FILE[] = "__file__";
133134

134135
#define VALID_CAPSULE_NAME "$valid$"
135136
#define INVALID_CAPSULE_NAME "$INvalid$"

0 commit comments

Comments
 (0)