msisupport.c 2.84 KB
Newer Older
Martin v. Löwis's avatar
Martin v. Löwis committed
1 2 3
#include "windows.h"
#include "msiquery.h"

4 5
int isWinNT;

Martin v. Löwis's avatar
Martin v. Löwis committed
6 7 8 9
/* Print a debug message to the installer log file.
 * To see the debug messages, install with
 * msiexec /i pythonxy.msi /l*v python.log
 */
10
static UINT debug(MSIHANDLE hInstall, LPCSTR msg)
Martin v. Löwis's avatar
Martin v. Löwis committed
11 12
{
	MSIHANDLE hRec = MsiCreateRecord(1);
13
	if (!hRec || MsiRecordSetStringA(hRec, 1, msg) != ERROR_SUCCESS) {
Martin v. Löwis's avatar
Martin v. Löwis committed
14 15 16 17 18 19 20 21 22 23 24 25
		return ERROR_INSTALL_FAILURE;
	}
	MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, hRec);
	MsiCloseHandle(hRec);
	return ERROR_SUCCESS;
}

/* Check whether the TARGETDIR exists and is a directory.
 * Set TargetExists appropriately.
 */
UINT __declspec(dllexport) __stdcall CheckDir(MSIHANDLE hInstall)
{
26 27 28
#define PSIZE 1024
	WCHAR wpath[PSIZE];
	char path[PSIZE];
Martin v. Löwis's avatar
Martin v. Löwis committed
29
	UINT result;
30
	DWORD size = PSIZE;
Martin v. Löwis's avatar
Martin v. Löwis committed
31
	DWORD attributes;
32 33

	isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
Martin v. Löwis's avatar
Martin v. Löwis committed
34
	
35 36 37 38
	if (isWinNT)
		result = MsiGetPropertyW(hInstall, L"TARGETDIR", wpath, &size);
	else
		result = MsiGetPropertyA(hInstall, "TARGETDIR", path, &size);
Martin v. Löwis's avatar
Martin v. Löwis committed
39 40
	if (result != ERROR_SUCCESS)
		return result;
41
	wpath[size] = L'\0';
Martin v. Löwis's avatar
Martin v. Löwis committed
42 43
	path[size] = L'\0';

44 45 46 47
	if (isWinNT)
		attributes = GetFileAttributesW(wpath);
	else
		attributes = GetFileAttributesA(path);
Martin v. Löwis's avatar
Martin v. Löwis committed
48 49 50
	if (attributes == INVALID_FILE_ATTRIBUTES ||
		!(attributes & FILE_ATTRIBUTE_DIRECTORY)) 
	{
51
		return MsiSetPropertyA(hInstall, "TargetExists", "0");
Martin v. Löwis's avatar
Martin v. Löwis committed
52
	} else {
53
		return MsiSetPropertyA(hInstall, "TargetExists", "1");
Martin v. Löwis's avatar
Martin v. Löwis committed
54 55 56 57 58 59 60 61 62 63 64 65
	}
}

/* Update the state of the REGISTRY.tcl component according to the
 * Extension and TclTk features. REGISTRY.tcl must be installed
 * if both features are installed, and must be absent otherwise.
 */
UINT __declspec(dllexport) __stdcall UpdateEditIDLE(MSIHANDLE hInstall)
{
	INSTALLSTATE ext_old, ext_new, tcl_old, tcl_new, reg_new;
	UINT result;

66
	result = MsiGetFeatureStateA(hInstall, "Extensions", &ext_old, &ext_new);
Martin v. Löwis's avatar
Martin v. Löwis committed
67 68
	if (result != ERROR_SUCCESS)
		return result;
69
	result = MsiGetFeatureStateA(hInstall, "TclTk", &tcl_old, &tcl_new);
Martin v. Löwis's avatar
Martin v. Löwis committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
	if (result != ERROR_SUCCESS)
		return result;

	/* If the current state is Absent, and the user did not select
	   the feature in the UI, Installer apparently sets the "selected"
	   state to unknown. Update it to the current value, then. */
	if (ext_new == INSTALLSTATE_UNKNOWN)
		ext_new = ext_old;
	if (tcl_new == INSTALLSTATE_UNKNOWN)
		tcl_new = tcl_old;

	// XXX consider current state of REGISTRY.tcl?
	if (((tcl_new == INSTALLSTATE_LOCAL) ||
		 (tcl_new == INSTALLSTATE_SOURCE) ||
		 (tcl_new == INSTALLSTATE_DEFAULT)) &&
		((ext_new == INSTALLSTATE_LOCAL) ||
		 (ext_new == INSTALLSTATE_SOURCE) ||
		 (ext_new == INSTALLSTATE_DEFAULT))) {
		reg_new = INSTALLSTATE_SOURCE;
	} else { 
		reg_new = INSTALLSTATE_ABSENT;
	}
92
	result = MsiSetComponentStateA(hInstall, "REGISTRY.tcl", reg_new);
Martin v. Löwis's avatar
Martin v. Löwis committed
93 94 95 96 97 98 99 100 101 102
	return result;
}

BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved)
{
    return TRUE;
}