@@ -171,8 +171,8 @@ static wchar_t * location_checks[] = {
171171 L"\\" ,
172172 L"\\PCBuild\\win32\\" ,
173173 L"\\PCBuild\\amd64\\" ,
174- // To support early 32bit versions of Python that stuck the build binaries
175- // directly in PCBuild...
174+ /* To support early 32bit versions of Python that stuck the build binaries
175+ * directly in PCBuild... */
176176 L"\\PCBuild\\" ,
177177 NULL
178178};
@@ -234,7 +234,7 @@ locate_pythons_for_key(HKEY root, REGSAM flags)
234234 status = RegOpenKeyExW (root , ip_path , 0 , flags , & ip_key );
235235 if (status != ERROR_SUCCESS ) {
236236 winerror (status , message , MSGSIZE );
237- // Note: 'message' already has a trailing \n
237+ /* Note: 'message' already has a trailing \n*/
238238 debug (L"%ls\\%ls: %ls" , key_name , ip_path , message );
239239 continue ;
240240 }
@@ -340,20 +340,20 @@ static void
340340locate_all_pythons ()
341341{
342342#if defined(_M_X64 )
343- // If we are a 64bit process, first hit the 32bit keys.
343+ /* If we are a 64bit process, first hit the 32bit keys. */
344344 debug (L"locating Pythons in 32bit registry\n" );
345345 locate_pythons_for_key (HKEY_CURRENT_USER , KEY_READ | KEY_WOW64_32KEY );
346346 locate_pythons_for_key (HKEY_LOCAL_MACHINE , KEY_READ | KEY_WOW64_32KEY );
347347#else
348- // If we are a 32bit process on a 64bit Windows, first hit the 64bit keys.
348+ /* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys.*/
349349 BOOL f64 = FALSE;
350350 if (IsWow64Process (GetCurrentProcess (), & f64 ) && f64 ) {
351351 debug (L"locating Pythons in 64bit registry\n" );
352352 locate_pythons_for_key (HKEY_CURRENT_USER , KEY_READ | KEY_WOW64_64KEY );
353353 locate_pythons_for_key (HKEY_LOCAL_MACHINE , KEY_READ | KEY_WOW64_64KEY );
354354 }
355355#endif
356- // now hit the "native" key for this process bittedness.
356+ /* now hit the "native" key for this process bittedness. */
357357 debug (L"locating Pythons in native registry\n" );
358358 locate_pythons_for_key (HKEY_CURRENT_USER , KEY_READ );
359359 locate_pythons_for_key (HKEY_LOCAL_MACHINE , KEY_READ );
@@ -370,8 +370,14 @@ find_python_by_version(wchar_t const * wanted_ver)
370370 size_t wlen = wcslen (wanted_ver );
371371 int bits = 0 ;
372372
373- if (wcsstr (wanted_ver , L"-32" ))
373+ if (wcsstr (wanted_ver , L"-32" )) {
374374 bits = 32 ;
375+ wlen -= wcslen (L"-32" );
376+ }
377+ else if (wcsstr (wanted_ver , L"-64" )) { /* Added option to select 64 bit explicitly */
378+ bits = 64 ;
379+ wlen -= wcslen (L"-64" );
380+ }
375381 for (i = 0 ; i < num_installed_pythons ; i ++ , ip ++ ) {
376382 n = wcslen (ip -> version );
377383 if (n > wlen )
@@ -608,14 +614,16 @@ run_child(wchar_t * cmdline)
608614 PROCESS_INFORMATION pi ;
609615
610616#if defined(_WINDOWS )
611- // When explorer launches a Windows (GUI) application, it displays
612- // the "app starting" (the "pointer + hourglass") cursor for a number
613- // of seconds, or until the app does something UI-ish (eg, creating a
614- // window, or fetching a message). As this launcher doesn't do this
615- // directly, that cursor remains even after the child process does these
616- // things. We avoid that by doing a simple post+get message.
617- // See http://bugs.python.org/issue17290 and
618- // https://bitbucket.org/vinay.sajip/pylauncher/issue/20/busy-cursor-for-a-long-time-when-running
617+ /*
618+ When explorer launches a Windows (GUI) application, it displays
619+ the "app starting" (the "pointer + hourglass") cursor for a number
620+ of seconds, or until the app does something UI-ish (eg, creating a
621+ window, or fetching a message). As this launcher doesn't do this
622+ directly, that cursor remains even after the child process does these
623+ things. We avoid that by doing a simple post+get message.
624+ See http://bugs.python.org/issue17290 and
625+ https://bitbucket.org/vinay.sajip/pylauncher/issue/20/busy-cursor-for-a-long-time-when-running
626+ */
619627 MSG msg ;
620628
621629 PostMessage (0 , 0 , 0 , 0 );
@@ -1040,32 +1048,49 @@ find_terminator(char * buffer, int len, BOM *bom)
10401048static BOOL
10411049validate_version (wchar_t * p )
10421050{
1043- BOOL result = TRUE;
1044-
1045- if (!isdigit (* p )) /* expect major version */
1046- result = FALSE;
1047- else if (* ++ p ) { /* more to do */
1048- if (* p != L'.' ) /* major/minor separator */
1051+ /*
1052+ Version information should start with one of 2 or 3,
1053+ Optionally followed by a period and a minor version,
1054+ Optionally followed by a minus and one of 32 or 64.
1055+ Valid examples:
1056+ 2
1057+ 3
1058+ 2.7
1059+ 3.6
1060+ 2.7-32
1061+ The intent is to add to the valid patterns:
1062+ 3.10
1063+ 3-32
1064+ 3.6-64
1065+ 3-64
1066+ */
1067+ BOOL result = (p != NULL ); /* Default to False if null pointer. */
1068+
1069+ result = result && iswdigit (* p ); /* Result = False if fist string element is not a digit. */
1070+
1071+ while (result && iswdigit (* p )) /* Require a major version */
1072+ ++ p ; /* Skip all leading digit(s) */
1073+ if (result && (* p == L'.' )) /* Allow . for major minor separator.*/
1074+ {
1075+ result = iswdigit (* ++ p ); /* Must be at least one digit */
1076+ while (result && iswdigit (* ++ p )) ; /* Skip any more Digits */
1077+ }
1078+ if (result && (* p == L'-' )) { /* Allow - for Bits Separator */
1079+ switch (* ++ p ){
1080+ case L'3' : /* 3 is OK */
1081+ result = (* ++ p == L'2' ) && !* ++ p ; /* only if followed by 2 and ended.*/
1082+ break ;
1083+ case L'6' : /* 6 is OK */
1084+ result = (* ++ p == L'4' ) && !* ++ p ; /* only if followed by 4 and ended.*/
1085+ break ;
1086+ default :
10491087 result = FALSE;
1050- else {
1051- ++ p ;
1052- if (!isdigit (* p )) /* expect minor version */
1053- result = FALSE;
1054- else {
1055- ++ p ;
1056- if (* p ) { /* more to do */
1057- if (* p != L'-' )
1058- result = FALSE;
1059- else {
1060- ++ p ;
1061- if ((* p != '3' ) && (* ++ p != '2' ) && !* ++ p )
1062- result = FALSE;
1063- }
1064- }
1065- }
1088+ break ;
10661089 }
10671090 }
1091+ result = result && !* p ; /* Must have reached EOS */
10681092 return result ;
1093+
10691094}
10701095
10711096typedef struct {
@@ -1529,7 +1554,7 @@ installed", &p[1]);
15291554#if defined(_M_X64 )
15301555 BOOL canDo64bit = TRUE;
15311556#else
1532- // If we are a 32bit process on a 64bit Windows, first hit the 64bit keys.
1557+ /* If we are a 32bit process on a 64bit Windows, first hit the 64bit keys. */
15331558 BOOL canDo64bit = FALSE;
15341559 IsWow64Process (GetCurrentProcess (), & canDo64bit );
15351560#endif
@@ -1538,15 +1563,20 @@ installed", &p[1]);
15381563 fwprintf (stdout , L"\
15391564Python Launcher for Windows Version %ls\n\n" , version_text );
15401565 fwprintf (stdout , L"\
1541- usage: %ls [ launcher-arguments ] [ python-arguments ] script [ script-arguments ]\n\n" , argv [0 ]);
1566+ usage:\n\
1567+ %ls [launcher-args] [python-args] script [script-args]\n\n" , argv [0 ]);
15421568 fputws (L"\
15431569Launcher arguments:\n\n\
15441570-2 : Launch the latest Python 2.x version\n\
15451571-3 : Launch the latest Python 3.x version\n\
15461572-X.Y : Launch the specified Python version\n" , stdout );
15471573 if (canDo64bit ) {
15481574 fputws (L"\
1549- -X.Y-32: Launch the specified 32bit Python version" , stdout );
1575+ The above all default to 64 bit if a matching 64 bit python is present.\n\
1576+ -X.Y-32: Launch the specified 32bit Python version\n\
1577+ -X-32 : Launch the latest 32bit Python X version\n\
1578+ -X.Y-64: Launch the specified 64bit Python version\n\
1579+ -X-64 : Launch the latest 64bit Python X version" , stdout );
15501580 }
15511581 fputws (L"\n\nThe following help text is from Python:\n\n" , stdout );
15521582 fflush (stdout );
0 commit comments