summaryrefslogtreecommitdiffstats
path: root/PC/getpath_nt.c
blob: d960d15ef536fda3f1f57cd0181fe2e35397317f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include "Python.h"
#include "osdefs.h"
#include <windows.h>

/* PREFIX and EXEC_PREFIX are meaningless on Windows */

#ifndef PREFIX
#define PREFIX ""
#endif

#ifndef EXEC_PREFIX
#define EXEC_PREFIX ""
#endif

/*
This is a special Win32 version of getpath.

* There is no default path.  There is nothing even remotely resembling
  a standard location.  Maybe later "Program Files/Python", but not yet.

* The Registry is used as the primary store for the Python path.

* The environment variable PYTHONPATH _overrides_ the registry.  This should
  allow a "standard" Python environment, but allow you to manually setup
  another (eg, a beta version).

*/

BOOL PyWin_IsWin32s()
{
	static BOOL bIsWin32s = -1; // flag as "not yet looked"

	if (bIsWin32s==-1) {
		OSVERSIONINFO ver;
		ver.dwOSVersionInfoSize = sizeof(ver);
		GetVersionEx(&ver);
		bIsWin32s = ver.dwPlatformId == VER_PLATFORM_WIN32s;
	}
	return bIsWin32s;
}

/* Load a PYTHONPATH value from the registry
   Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER

   Returns NULL, or a pointer that should be free'd.
*/
static char *
getpythonregpath(HKEY keyBase, BOOL bWin32s)
{
	HKEY newKey = 0;
	DWORD nameSize = 0;
	DWORD dataSize = 0;
	DWORD numEntries = 0;
	LONG rc;
	char *retval = NULL;
	char *dataBuf;
	if ((rc=RegOpenKey(keyBase, "Software\\Python\\PythonCore\\" MS_DLL_ID "\\PythonPath", 
	                   &newKey))==ERROR_SUCCESS) {
		RegQueryInfoKey(newKey, NULL, NULL, NULL, NULL, NULL, NULL, 
		                &numEntries, &nameSize, &dataSize, NULL, NULL );
	}
	if (bWin32s && numEntries==0 && dataSize==0) { /* must hardcode for Win32s */
		numEntries = 1;
		dataSize = 511;
	}
	if (numEntries) {
		/* Loop over all subkeys. */
		/* Win32s doesnt know how many subkeys, so we do
		   it twice */
		char keyBuf[MAX_PATH+1];
		int index = 0;
		int off = 0;
		for(index=0;;index++) {
			long reqdSize = 0;
			DWORD rc = RegEnumKey(newKey, index, keyBuf,MAX_PATH+1);
			if (rc) break;
			rc = RegQueryValue(newKey, keyBuf, NULL, &reqdSize);
			if (rc) break;
			if (bWin32s && reqdSize==0) reqdSize = 512;
			dataSize += reqdSize + 1; /* 1 for the ";" */
		}
		dataBuf = malloc(dataSize+1);
		if (dataBuf==NULL) return NULL; /* pretty serious?  Raise error? */
		/* Now loop over, grabbing the paths.  Subkeys before main library */
		for(index=0;;index++) {
			int adjust;
			long reqdSize = dataSize;
			DWORD rc = RegEnumKey(newKey, index, keyBuf,MAX_PATH+1);
			if (rc) break;
			rc = RegQueryValue(newKey, keyBuf, dataBuf+off, &reqdSize);
			if (rc) break;
			if (reqdSize>1) { // If Nothing, or only '\0' copied.
				adjust = strlen(dataBuf+off);
				dataSize -= adjust;
				off += adjust;
				dataBuf[off++] = ';';
				dataBuf[off] = '\0';
				dataSize--;
			}
		}
		/* Additionally, win32s doesnt work as expected, so
		   the specific strlen() is required for 3.1. */
		rc = RegQueryValue(newKey, "", dataBuf+off, &dataSize);
		if (rc==ERROR_SUCCESS) {
			if (strlen(dataBuf)==0)
				free(dataBuf);
			else
				retval = dataBuf; // caller will free
		}
		else
			free(dataBuf);
	}

	if (newKey)
		RegCloseKey(newKey);
	return retval;
}
/* Return the initial python search path.  This is called once from
   initsys() to initialize sys.path.  The environment variable
   PYTHONPATH is fetched and the default path appended.  The default
   path may be passed to the preprocessor; if not, a system-dependent
   default is used. */

char *
Py_GetPath()
{
	char *path = getenv("PYTHONPATH");
	char *defpath = PYTHONPATH;
	static char *buf = NULL;
	char *p;
	int n;
	extern char *Py_GetProgramName();

	if (buf != NULL) {
		free(buf);
		buf = NULL;
	}

	if (path == NULL) {
		char *machinePath, *userPath;
		int machineLen, userLen;
		/* lookup the registry */
		BOOL bWin32s = PyWin_IsWin32s();

		if (bWin32s) { /* are we running under Windows 3.1 Win32s */
			/* only CLASSES_ROOT is supported */
			machinePath = getpythonregpath(HKEY_CLASSES_ROOT, TRUE); 
			userPath = NULL;
		} else {
			machinePath = getpythonregpath(HKEY_LOCAL_MACHINE, FALSE);
			userPath = getpythonregpath(HKEY_CURRENT_USER, FALSE);
		}
		if (machinePath==NULL && userPath==NULL) return defpath;
		machineLen = machinePath ? strlen(machinePath) : 0;
		userLen = userPath ? strlen(userPath) : 0;
		n = machineLen + userLen + 1;
		// this is a memory leak, as Python never frees it.  Only ever called once, so big deal!
		buf = malloc(n);
		if (buf == NULL)
			Py_FatalError("not enough memory to copy module search path");
		p = buf;
		*p = '\0';
		if (machineLen) {
			strcpy(p, machinePath);
			p += machineLen;
		}
		if (userLen) {
			if (machineLen)
				*p++ = DELIM;
			strcpy(p, userPath);
		}
		if (userPath) free(userPath);
		if (machinePath) free(machinePath);
	} else {
		
		buf = malloc(strlen(path)+1);
		if (buf == NULL)
			Py_FatalError("not enough memory to copy module search path");
		strcpy(buf, path);
	}
	return buf;
}

/* Similar for Makefile variables $prefix and $exec_prefix */

char *
Py_GetPrefix()
{
	return PREFIX;
}

char *
Py_GetExecPrefix()
{
	return EXEC_PREFIX;
}

char *
Py_GetProgramFullPath()
{
	extern char *Py_GetProgramName();
	return Py_GetProgramName();
}