Add associator

This commit is contained in:
Brian Curtin 2012-06-20 22:48:54 -05:00
parent 4bca286160
commit 9698bde3c2
6 changed files with 2438 additions and 0 deletions

731
PC/associator.c Normal file
View File

@ -0,0 +1,731 @@
/*
* Copyright (C) 2011-2012 Vinay Sajip. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "associator.h"
#define PYTHON_EXECUTABLE L"python.exe"
#define MSGSIZE 1024
#define MAX_VERSION_SIZE 4
typedef struct {
wchar_t version[MAX_VERSION_SIZE]; /* m.n */
int bits; /* 32 or 64 */
wchar_t executable[MAX_PATH];
} INSTALLED_PYTHON;
/*
* To avoid messing about with heap allocations, just assume we can allocate
* statically and never have to deal with more versions than this.
*/
#define MAX_INSTALLED_PYTHONS 100
static INSTALLED_PYTHON installed_pythons[MAX_INSTALLED_PYTHONS];
static size_t num_installed_pythons = 0;
/* to hold SOFTWARE\Python\PythonCore\X.Y\InstallPath */
#define IP_BASE_SIZE 40
#define IP_SIZE (IP_BASE_SIZE + MAX_VERSION_SIZE)
#define CORE_PATH L"SOFTWARE\\Python\\PythonCore"
static wchar_t * location_checks[] = {
L"\\",
/*
L"\\PCBuild\\",
L"\\PCBuild\\amd64\\",
*/
NULL
};
static wchar_t *
skip_whitespace(wchar_t * p)
{
while (*p && isspace(*p))
++p;
return p;
}
/*
* This function is here to minimise Visual Studio
* warnings about security implications of getenv, and to
* treat blank values as if they are absent.
*/
static wchar_t * get_env(wchar_t * key)
{
wchar_t * result = _wgetenv(key);
if (result) {
result = skip_whitespace(result);
if (*result == L'\0')
result = NULL;
}
return result;
}
static FILE * log_fp = NULL;
static void
debug(wchar_t * format, ...)
{
va_list va;
if (log_fp != NULL) {
va_start(va, format);
vfwprintf_s(log_fp, format, va);
}
}
static void winerror(int rc, wchar_t * message, int size)
{
FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
message, size, NULL);
}
static INSTALLED_PYTHON *
find_existing_python(wchar_t * path)
{
INSTALLED_PYTHON * result = NULL;
size_t i;
INSTALLED_PYTHON * ip;
for (i = 0, ip = installed_pythons; i < num_installed_pythons; i++, ip++) {
if (_wcsicmp(path, ip->executable) == 0) {
result = ip;
break;
}
}
return result;
}
static void
locate_pythons_for_key(HKEY root, REGSAM flags)
{
HKEY core_root, ip_key;
LSTATUS status = RegOpenKeyExW(root, CORE_PATH, 0, flags, &core_root);
wchar_t message[MSGSIZE];
DWORD i;
size_t n;
BOOL ok;
DWORD type, data_size, attrs;
INSTALLED_PYTHON * ip, * pip;
wchar_t ip_path[IP_SIZE];
wchar_t * check;
wchar_t ** checkp;
wchar_t *key_name = (root == HKEY_LOCAL_MACHINE) ? L"HKLM" : L"HKCU";
if (status != ERROR_SUCCESS)
debug(L"locate_pythons_for_key: unable to open PythonCore key in %s\n",
key_name);
else {
ip = &installed_pythons[num_installed_pythons];
for (i = 0; num_installed_pythons < MAX_INSTALLED_PYTHONS; i++) {
status = RegEnumKeyW(core_root, i, ip->version, MAX_VERSION_SIZE);
if (status != ERROR_SUCCESS) {
if (status != ERROR_NO_MORE_ITEMS) {
/* unexpected error */
winerror(status, message, MSGSIZE);
debug(L"Can't enumerate registry key for version %s: %s\n",
ip->version, message);
}
break;
}
else {
_snwprintf_s(ip_path, IP_SIZE, _TRUNCATE,
L"%s\\%s\\InstallPath", CORE_PATH, ip->version);
status = RegOpenKeyExW(root, ip_path, 0, flags, &ip_key);
if (status != ERROR_SUCCESS) {
winerror(status, message, MSGSIZE);
// Note: 'message' already has a trailing \n
debug(L"%s\\%s: %s", key_name, ip_path, message);
continue;
}
data_size = sizeof(ip->executable) - 1;
status = RegQueryValueEx(ip_key, NULL, NULL, &type,
(LPBYTE) ip->executable, &data_size);
RegCloseKey(ip_key);
if (status != ERROR_SUCCESS) {
winerror(status, message, MSGSIZE);
debug(L"%s\\%s: %s\n", key_name, ip_path, message);
continue;
}
if (type == REG_SZ) {
data_size = data_size / sizeof(wchar_t) - 1; /* for NUL */
if (ip->executable[data_size - 1] == L'\\')
--data_size; /* reg value ended in a backslash */
/* ip->executable is data_size long */
for (checkp = location_checks; *checkp; ++checkp) {
check = *checkp;
_snwprintf_s(&ip->executable[data_size],
MAX_PATH - data_size,
MAX_PATH - data_size,
L"%s%s", check, PYTHON_EXECUTABLE);
attrs = GetFileAttributesW(ip->executable);
if (attrs == INVALID_FILE_ATTRIBUTES) {
winerror(GetLastError(), message, MSGSIZE);
debug(L"locate_pythons_for_key: %s: %s",
ip->executable, message);
}
else if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
debug(L"locate_pythons_for_key: '%s' is a \
directory\n",
ip->executable, attrs);
}
else if (find_existing_python(ip->executable)) {
debug(L"locate_pythons_for_key: %s: already \
found: %s\n", ip->executable);
}
else {
/* check the executable type. */
ok = GetBinaryTypeW(ip->executable, &attrs);
if (!ok) {
debug(L"Failure getting binary type: %s\n",
ip->executable);
}
else {
if (attrs == SCS_64BIT_BINARY)
ip->bits = 64;
else if (attrs == SCS_32BIT_BINARY)
ip->bits = 32;
else
ip->bits = 0;
if (ip->bits == 0) {
debug(L"locate_pythons_for_key: %s: \
invalid binary type: %X\n",
ip->executable, attrs);
}
else {
if (wcschr(ip->executable, L' ') != NULL) {
/* has spaces, so quote */
n = wcslen(ip->executable);
memmove(&ip->executable[1],
ip->executable, n * sizeof(wchar_t));
ip->executable[0] = L'\"';
ip->executable[n + 1] = L'\"';
ip->executable[n + 2] = L'\0';
}
debug(L"locate_pythons_for_key: %s \
is a %dbit executable\n",
ip->executable, ip->bits);
++num_installed_pythons;
pip = ip++;
if (num_installed_pythons >=
MAX_INSTALLED_PYTHONS)
break;
/* Copy over the attributes for the next */
*ip = *pip;
}
}
}
}
}
}
}
RegCloseKey(core_root);
}
}
static int
compare_pythons(const void * p1, const void * p2)
{
INSTALLED_PYTHON * ip1 = (INSTALLED_PYTHON *) p1;
INSTALLED_PYTHON * ip2 = (INSTALLED_PYTHON *) p2;
/* note reverse sorting on version */
int result = wcscmp(ip2->version, ip1->version);
if (result == 0)
result = ip2->bits - ip1->bits; /* 64 before 32 */
return result;
}
static void
locate_all_pythons()
{
#if defined(_M_X64)
// If we are a 64bit process, first hit the 32bit keys.
debug(L"locating Pythons in 32bit registry\n");
locate_pythons_for_key(HKEY_CURRENT_USER, KEY_READ | KEY_WOW64_32KEY);
locate_pythons_for_key(HKEY_LOCAL_MACHINE, KEY_READ | KEY_WOW64_32KEY);
#else
// If we are a 32bit process on a 64bit Windows, first hit the 64bit keys.
BOOL f64 = FALSE;
if (IsWow64Process(GetCurrentProcess(), &f64) && f64) {
debug(L"locating Pythons in 64bit registry\n");
locate_pythons_for_key(HKEY_CURRENT_USER, KEY_READ | KEY_WOW64_64KEY);
locate_pythons_for_key(HKEY_LOCAL_MACHINE, KEY_READ | KEY_WOW64_64KEY);
}
#endif
// now hit the "native" key for this process bittedness.
debug(L"locating Pythons in native registry\n");
locate_pythons_for_key(HKEY_CURRENT_USER, KEY_READ);
locate_pythons_for_key(HKEY_LOCAL_MACHINE, KEY_READ);
qsort(installed_pythons, num_installed_pythons, sizeof(INSTALLED_PYTHON),
compare_pythons);
}
typedef struct {
wchar_t * path;
wchar_t * key;
wchar_t * value;
} REGISTRY_ENTRY;
static REGISTRY_ENTRY registry_entries[] = {
{ L".py", NULL, L"Python.File" },
{ L".pyc", NULL, L"Python.CompiledFile" },
{ L".pyo", NULL, L"Python.CompiledFile" },
{ L".pyw", NULL, L"Python.NoConFile" },
{ L"Python.CompiledFile", NULL, L"Compiled Python File" },
{ L"Python.CompiledFile\\DefaultIcon", NULL, L"pyc.ico" },
{ L"Python.CompiledFile\\shell\\open", NULL, L"Open" },
{ L"Python.CompiledFile\\shell\\open\\command", NULL, L"python.exe" },
{ L"Python.File", NULL, L"Python File" },
{ L"Python.File\\DefaultIcon", NULL, L"py.ico" },
{ L"Python.File\\shell\\open", NULL, L"Open" },
{ L"Python.File\\shell\\open\\command", NULL, L"python.exe" },
{ L"Python.NoConFile", NULL, L"Python File (no console)" },
{ L"Python.NoConFile\\DefaultIcon", NULL, L"py.ico" },
{ L"Python.NoConFile\\shell\\open", NULL, L"Open" },
{ L"Python.NoConFile\\shell\\open\\command", NULL, L"pythonw.exe" },
{ NULL }
};
static BOOL
do_association(INSTALLED_PYTHON * ip)
{
LONG rc;
BOOL result = TRUE;
REGISTRY_ENTRY * rp = registry_entries;
wchar_t value[MAX_PATH];
wchar_t root[MAX_PATH];
wchar_t message[MSGSIZE];
wchar_t * pvalue;
HKEY hKey;
DWORD len;
wcsncpy_s(root, MAX_PATH, ip->executable, _TRUNCATE);
pvalue = wcsrchr(root, '\\');
if (pvalue)
*pvalue = L'\0';
for (; rp->path; ++rp) {
if (wcsstr(rp->path, L"DefaultIcon")) {
pvalue = value;
_snwprintf_s(value, MAX_PATH, _TRUNCATE,
L"%s\\DLLs\\%s", root, rp->value);
}
else if (wcsstr(rp->path, L"open\\command")) {
pvalue = value;
_snwprintf_s(value, MAX_PATH, _TRUNCATE,
L"%s\\%s \"%%1\" %%*", root, rp->value);
}
else {
pvalue = rp->value;
}
/* use rp->path, rp->key, pvalue */
/* NOTE: size is in bytes */
len = (DWORD) ((1 + wcslen(pvalue)) * sizeof(wchar_t));
rc = RegOpenKeyEx(HKEY_CLASSES_ROOT, rp->path, 0, KEY_SET_VALUE, &hKey);
if (rc == ERROR_SUCCESS) {
rc = RegSetValueExW(hKey, rp->key, 0, REG_SZ, (LPBYTE) pvalue, len);
RegCloseKey(hKey);
}
if (rc != ERROR_SUCCESS) {
winerror(rc, message, MSGSIZE);
MessageBoxW(NULL, message, L"Unable to set file associations", MB_OK | MB_ICONSTOP);
result = FALSE;
break;
}
}
return result;
}
static BOOL
associations_exist()
{
BOOL result = FALSE;
REGISTRY_ENTRY * rp = registry_entries;
wchar_t buffer[MSGSIZE];
LONG csize = MSGSIZE * sizeof(wchar_t);
LONG rc;
/* Currently, if any is found, we assume they're all there. */
for (; rp->path; ++rp) {
LONG size = csize;
rc = RegQueryValueW(HKEY_CLASSES_ROOT, rp->path, buffer, &size);
if (rc == ERROR_SUCCESS) {
result = TRUE;
break;
}
}
return result;
}
/* --------------------------------------------------------------------*/
static BOOL CALLBACK
find_by_title(HWND hwnd, LPARAM lParam)
{
wchar_t buffer[MSGSIZE];
BOOL not_found = TRUE;
wchar_t * p = (wchar_t *) GetWindowTextW(hwnd, buffer, MSGSIZE);
if (wcsstr(buffer, L"Python Launcher") == buffer) {
not_found = FALSE;
*((HWND *) lParam) = hwnd;
}
return not_found;
}
static HWND
find_installer_window()
{
HWND result = NULL;
BOOL found = EnumWindows(find_by_title, (LPARAM) &result);
return result;
}
static void
centre_window_in_front(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;
//make the window relative to its parent
screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
hwndParent = GetParent(hwnd);
GetWindowRect(hwnd, &rect);
if (hwndParent) {
GetWindowRect(hwndParent, &rectP);
}
else {
rectP.left = rectP.top = 0;
rectP.right = screenwidth;
rectP.bottom = screenheight;
}
width = rect.right - rect.left;
height = rect.bottom - rect.top;
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
//make sure that the dialog box never moves outside of
//the screen
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (x + width > screenwidth)
x = screenwidth - width;
if (y + height > screenheight)
y = screenheight - height;
SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, SWP_SHOWWINDOW);
}
static void
init_list(HWND hList)
{
LVCOLUMNW column;
LVITEMW item;
int colno = 0;
int width = 0;
int row;
size_t i;
INSTALLED_PYTHON * ip;
RECT r;
LPARAM style;
GetClientRect(hList, &r);
style = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE,
0, style | LVS_EX_FULLROWSELECT);
/* First set up the columns */
memset(&column, 0, sizeof(column));
column.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
column.pszText = L"Version";
column.cx = 60;
width += column.cx;
SendMessage(hList, LVM_INSERTCOLUMN, colno++,(LPARAM) &column);
#if defined(_M_X64)
column.pszText = L"Bits";
column.cx = 40;
column.iSubItem = colno;
SendMessage(hList, LVM_INSERTCOLUMN, colno++,(LPARAM) &column);
width += column.cx;
#endif
column.pszText = L"Path";
column.cx = r.right - r.top - width;
column.iSubItem = colno;
SendMessage(hList, LVM_INSERTCOLUMN, colno++,(LPARAM) &column);
/* Then insert the rows */
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT;
for (i = 0, ip = installed_pythons; i < num_installed_pythons; i++,ip++) {
item.iItem = (int) i;
item.iSubItem = 0;
item.pszText = ip->version;
colno = 0;
row = (int) SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM) &item);
#if defined(_M_X64)
item.iSubItem = ++colno;
item.pszText = (ip->bits == 64) ? L"64": L"32";
SendMessage(hList, LVM_SETITEM, row, (LPARAM) &item);
#endif
item.iSubItem = ++colno;
item.pszText = ip->executable;
SendMessage(hList, LVM_SETITEM, row, (LPARAM) &item);
}
}
/* ----------------------------------------------------------------*/
typedef int (__stdcall *MSGBOXWAPI)(IN HWND hWnd,
IN LPCWSTR lpText, IN LPCWSTR lpCaption,
IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);
int MessageBoxTimeoutW(IN HWND hWnd, IN LPCWSTR lpText,
IN LPCWSTR lpCaption, IN UINT uType,
IN WORD wLanguageId, IN DWORD dwMilliseconds);
#define MB_TIMEDOUT 32000
int MessageBoxTimeoutW(HWND hWnd, LPCWSTR lpText,
LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds)
{
static MSGBOXWAPI MsgBoxTOW = NULL;
if (!MsgBoxTOW) {
HMODULE hUser32 = GetModuleHandleW(L"user32.dll");
if (hUser32)
MsgBoxTOW = (MSGBOXWAPI)GetProcAddress(hUser32,
"MessageBoxTimeoutW");
else {
//stuff happened, add code to handle it here
//(possibly just call MessageBox())
return 0;
}
}
if (MsgBoxTOW)
return MsgBoxTOW(hWnd, lpText, lpCaption, uType, wLanguageId,
dwMilliseconds);
return 0;
}
/* ----------------------------------------------------------------*/
static INT_PTR CALLBACK
DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hList;
HWND hChild;
static int selected_index = -1;
WORD low = LOWORD(wParam);
wchar_t confirmation[MSGSIZE];
BOOL result = FALSE;
debug(L"DialogProc entry: 0x%02X\n", message);
switch (message) {
case WM_INITDIALOG:
hList = GetDlgItem(hDlg, IDC_LIST1);
init_list(hList);
SetFocus(hList);
result = TRUE;
break;
case WM_COMMAND:
if((low == IDOK) || (low == IDCANCEL)) {
HMODULE hUser32 = LoadLibraryW(L"user32.dll");
if (low == IDCANCEL)
wcsncpy_s(confirmation, MSGSIZE, L"No association was \
performed.", _TRUNCATE);
else {
if (selected_index < 0) {
/* should never happen */
wcsncpy_s(confirmation, MSGSIZE, L"The Python version to \
associate with couldn't be determined.", _TRUNCATE);
}
else {
INSTALLED_PYTHON * ip = &installed_pythons[selected_index];
/* Do the association and set the message. */
do_association(ip);
_snwprintf_s(confirmation, MSGSIZE, _TRUNCATE,
L"Associated Python files with the Python %s \
found at '%s'", ip->version, ip->executable);
}
}
if (hUser32) {
MessageBoxTimeoutW(hDlg,
confirmation,
L"Association Status",
MB_OK | MB_SETFOREGROUND |
MB_ICONINFORMATION,
0, 2000);
FreeLibrary(hUser32);
}
PostQuitMessage(0);
EndDialog(hDlg, 0);
result = TRUE;
}
break;
case WM_NOTIFY:
if (low == IDC_LIST1) {
NMLISTVIEW * p = (NMLISTVIEW *) lParam;
if ((p->hdr.code == LVN_ITEMCHANGED) &&
(p->uNewState & LVIS_SELECTED)) {
hChild = GetDlgItem(hDlg, IDOK);
selected_index = p->iItem;
EnableWindow(hChild, selected_index >= 0);
}
result = TRUE;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
result = TRUE;
break;
case WM_CLOSE:
DestroyWindow(hDlg);
result = TRUE;
break;
}
debug(L"DialogProc exit: %d\n", result);
return result;
}
int WINAPI wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nShow)
{
MSG msg;
HWND hDialog = 0;
HICON hIcon;
HWND hParent;
int status;
DWORD dw;
INITCOMMONCONTROLSEX icx;
wchar_t * wp;
wp = get_env(L"PYASSOC_DEBUG");
if ((wp != NULL) && (*wp != L'\0')) {
fopen_s(&log_fp, "c:\\temp\\associator.log", "w");
}
if (!lpCmdLine) {
debug(L"No command line specified.\n");
return 0;
}
if (!wcsstr(lpCmdLine, L"nocheck") &&
associations_exist()) /* Could have been restored by uninstall. */
return 0;
locate_all_pythons();
if (num_installed_pythons == 0)
return 0;
debug(L"%d pythons found.\n", num_installed_pythons);
/*
* OK, now there's something to do.
*
* We need to find the installer window to be the parent of
* our dialog, otherwise our dialog will be behind it.
*
* First, initialize common controls. If you don't - on
* some machines it works fine, on others the dialog never
* appears!
*/
icx.dwSize = sizeof(icx);
icx.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icx);
hParent = find_installer_window();
debug(L"installer window: %X\n", hParent);
hDialog = CreateDialogW(hInstance, MAKEINTRESOURCE(DLG_MAIN), hParent,
DialogProc);
dw = GetLastError();
debug(L"dialog created: %X: error: %X\n", hDialog, dw);
if (!hDialog)
{
wchar_t buf [100];
_snwprintf_s(buf, 100, _TRUNCATE, L"Error 0x%x", GetLastError());
MessageBoxW(0, buf, L"CreateDialog", MB_ICONEXCLAMATION | MB_OK);
return 1;
}
centre_window_in_front(hDialog);
hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE(DLG_ICON));
if( hIcon )
{
SendMessage(hDialog, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
SendMessage(hDialog, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
DestroyIcon(hIcon);
}
while ((status = GetMessage (& msg, 0, 0, 0)) != 0)
{
if (status == -1)
return -1;
if (!IsDialogMessage(hDialog, & msg))
{
TranslateMessage( & msg );
DispatchMessage( & msg );
}
}
return (int) msg.wParam;
}

1480
PC/associator.h Normal file

File diff suppressed because it is too large Load Diff

97
PC/associator.rc Normal file
View File

@ -0,0 +1,97 @@
// Microsoft Visual C++ generated resource script.
//
#include "associator.h"
#include "winuser.h"
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
DLG_ICON ICON "launcher.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
DLG_MAIN DIALOGEX 20, 40, 236, 183
// Make the dialog visible after positioning at centre
STYLE DS_SETFONT | DS_3DLOOK | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_NOPARENTNOTIFY
CAPTION "Python File Associations Have Ceased To Be!"
FONT 10, "Arial", 400, 0, 0x0
BEGIN
LTEXT "You've uninstalled the Python Launcher, so now there are no applications associated with Python files.",IDC_STATIC,7,7,225,18
LTEXT "You may wish to associate Python files with one of the Python versions installed on your machine, listed below:",IDC_STATIC,7,27,225,18
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,6,49,224,105
PUSHBUTTON "&Associate with selected Python",IDOK,6,164,117,14,WS_DISABLED
PUSHBUTTON "Do&n't associate Python files",IDCANCEL,128,164,102,14
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
DLG_MAIN, DIALOG
BEGIN
RIGHTMARGIN, 238
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{023B3CDA-59C8-45FD-95DC-F8973322ED34}</ProjectGuid>
<RootNamespace>associator</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
<Import Project="debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
<Import Project="release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\PC\associator.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\associator.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\PC\associator.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\PC\associator.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\associator.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\PC\associator.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -72,6 +72,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pylauncher", "pylauncher.vc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pywlauncher", "pywlauncher.vcxproj", "{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "associator", "associator.vcxproj", "{023B3CDA-59C8-45FD-95DC-F8973322ED34}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -597,6 +599,18 @@ Global
{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}.Release|Win32.Build.0 = Release|Win32
{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}.Release|x64.ActiveCfg = Release|x64
{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}.Release|x64.Build.0 = Release|x64
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Debug|Win32.ActiveCfg = Debug|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Debug|Win32.Build.0 = Debug|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Debug|x64.ActiveCfg = Debug|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGInstrument|Win32.ActiveCfg = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGInstrument|Win32.Build.0 = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGInstrument|x64.ActiveCfg = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGUpdate|Win32.ActiveCfg = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGUpdate|Win32.Build.0 = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.PGUpdate|x64.ActiveCfg = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Release|Win32.ActiveCfg = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Release|Win32.Build.0 = Release|Win32
{023B3CDA-59C8-45FD-95DC-F8973322ED34}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE