1

I have a quick question that I cannot seem to clarify, despite my research on Stack Overflow and beyond. My questions involves the Windows SystemParametersInfo function with its variants SystemParametersInfoW (Unicode) and SystemParametersInfoA (ANSI) in relation to a Python 3.x script.

In a Python script I am writing, I came across two different explanations into when to use these variants. This answer to a question says that for 64-bit machines you must use SystemParametersInfoW while for 32-bit machines you must use SystemParametersInfoA, thus you should run a function to determine which bit machine the script is running on. However, another answer here (and I've seen more people advocate for this type of answer) and here says that SystemParametersInfoW must be used with Python 3.x since it passes a Unicode string while SystemParametersInfoA is used for Python 2.x and below since it passes a byte string conducive with ANSI.

So what is the right answer here as I would need to proceed forward differently with my script? Again, I am using Python 3.5 so it would make sense that the second answer fits, however is there any truth in the bit of the machine being a factor between using SystemParametersInfoW and SystemParametersInfoA? Is it a mixture of both answers or should I go ahead and use SystemParametersInfoW regardless of whether it will be used on a 32 or 64 bit machine? Do I even need to determine the bit of the machine the script is running on? Thank you for your help in clarifying this issue!

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
J. Squillaro
  • 155
  • 2
  • 13
  • 1
    The 32-bit/64-bit thing is utter nonsense. If your programming language supports Unicode strings, go ahead and use the Unicode version - you needn't worry about what version of Windows you're running. (Well, unless you need to support Windows 95/98/ME, or 16-bit Windows, I suppose. Pretty unlikely nowadays!) – Harry Johnston Jul 02 '17 at 06:31
  • 1
    File/registry names, window text, user names, etc are all Unicode. Going through the ANSI API gives you a worse-than-worthless lossy translation to the locale codepage. Let codepages die and bury them with MS-DOS and Windows 9.x (basically a 32-bit DOS extender at its core). No supported build of Python runs on those old systems. Users of Python 2 should use `unicode` strings whenever calling WinAPI functions, which unfortunately drives a wedge between Unix and Windows code, but that's just a hard fact of cross-platform code. – Eryk Sun Jul 02 '17 at 13:17

2 Answers2

6

Internally, Windows uses Unicode. The SystemParametersInfoA function converts ANSI parameter strings to Unicode and internally calls SystemParametersInfoW. You can call either from Python whether 32- or 64-bit, in Python 2.x or 3.x. Usually you want the W version to pass and retrieve Unicode strings since Windows is internally Unicode. The A version can lose information.

Example that works in Python 2 or 3, 32- or 64-bit. Note that the W version returns a Unicode string in the buffer, while the A version returns a byte string.

from __future__ import print_function
from ctypes import *
import sys

print(sys.version)
SPI_GETDESKWALLPAPER = 0x0073
dll = WinDLL('user32')
buf = create_string_buffer(200)
ubuf = create_unicode_buffer(200)
if dll.SystemParametersInfoA(SPI_GETDESKWALLPAPER,200,buf,0):
    print(buf.value)
if dll.SystemParametersInfoW(SPI_GETDESKWALLPAPER,200,ubuf,0):
    print(ubuf.value)

Output (Python 2.X 32-bit and Python 3.X 64-bit):

C:\>py -2 test.py
2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)]
c:\windows\web\wallpaper\theme1\img1.jpg
c:\windows\web\wallpaper\theme1\img1.jpg

C:\>py -3 test.py
3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
b'c:\\windows\\web\\wallpaper\\theme1\\img1.jpg'
c:\windows\web\wallpaper\theme1\img1.jpg
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
2

On Windows 3.x/95/98/ME it is likely that only SystemParametersInfoA works correctly. On all other systems both the A and W flavor will work regardless of the OS bitness.

Assuming you only support "recent" versions of Windows, you should just pick the flavor most comfortable for you to use in your language and that usually means the flavor that matches the default string type in your language.

If you want to support both Python v2 & v3 you would have to choose at run-time which function to call if you are using the default string type.

Anders
  • 97,548
  • 12
  • 110
  • 164
  • I see. Thank you for reminding me about the part of supporting both versions of Python. This didn't pass my mind since I write in Python 3 but some systems will only have Python 2! – J. Squillaro Jul 03 '17 at 18:20