Issue #7194: test_thread could try to release an unacquired mutex (and fail).
[python.git] / PC / msvcrtmodule.c
blobcad22b19e0a0d3ae31b0a9be851ad6c0d8395bce
1 /*********************************************************
3 msvcrtmodule.c
5 A Python interface to the Microsoft Visual C Runtime
6 Library, providing access to those non-portable, but
7 still useful routines.
9 Only ever compiled with an MS compiler, so no attempt
10 has been made to avoid MS language extensions, etc...
12 This may only work on NT or 95...
14 Author: Mark Hammond and Guido van Rossum.
15 Maintenance: Guido van Rossum.
17 ***********************************************************/
19 #include "Python.h"
20 #include "malloc.h"
21 #include <io.h>
22 #include <conio.h>
23 #include <sys/locking.h>
25 #ifdef _MSC_VER
26 #if _MSC_VER >= 1500
27 #include <crtassem.h>
28 #endif
29 #endif
31 // Force the malloc heap to clean itself up, and free unused blocks
32 // back to the OS. (According to the docs, only works on NT.)
33 static PyObject *
34 msvcrt_heapmin(PyObject *self, PyObject *args)
36 if (!PyArg_ParseTuple(args, ":heapmin"))
37 return NULL;
39 if (_heapmin() != 0)
40 return PyErr_SetFromErrno(PyExc_IOError);
42 Py_INCREF(Py_None);
43 return Py_None;
46 // Perform locking operations on a C runtime file descriptor.
47 static PyObject *
48 msvcrt_locking(PyObject *self, PyObject *args)
50 int fd;
51 int mode;
52 long nbytes;
53 int err;
55 if (!PyArg_ParseTuple(args, "iil:locking", &fd, &mode, &nbytes))
56 return NULL;
58 Py_BEGIN_ALLOW_THREADS
59 err = _locking(fd, mode, nbytes);
60 Py_END_ALLOW_THREADS
61 if (err != 0)
62 return PyErr_SetFromErrno(PyExc_IOError);
64 Py_INCREF(Py_None);
65 return Py_None;
68 // Set the file translation mode for a C runtime file descriptor.
69 static PyObject *
70 msvcrt_setmode(PyObject *self, PyObject *args)
72 int fd;
73 int flags;
74 if (!PyArg_ParseTuple(args,"ii:setmode", &fd, &flags))
75 return NULL;
77 flags = _setmode(fd, flags);
78 if (flags == -1)
79 return PyErr_SetFromErrno(PyExc_IOError);
81 return PyInt_FromLong(flags);
84 // Convert an OS file handle to a C runtime file descriptor.
85 static PyObject *
86 msvcrt_open_osfhandle(PyObject *self, PyObject *args)
88 long handle;
89 int flags;
90 int fd;
92 if (!PyArg_ParseTuple(args, "li:open_osfhandle", &handle, &flags))
93 return NULL;
95 fd = _open_osfhandle(handle, flags);
96 if (fd == -1)
97 return PyErr_SetFromErrno(PyExc_IOError);
99 return PyInt_FromLong(fd);
102 // Convert a C runtime file descriptor to an OS file handle.
103 static PyObject *
104 msvcrt_get_osfhandle(PyObject *self, PyObject *args)
106 int fd;
107 Py_intptr_t handle;
109 if (!PyArg_ParseTuple(args,"i:get_osfhandle", &fd))
110 return NULL;
112 handle = _get_osfhandle(fd);
113 if (handle == -1)
114 return PyErr_SetFromErrno(PyExc_IOError);
116 /* technically 'handle' is not a pointer, but a integer as
117 large as a pointer, Python's *VoidPtr interface is the
118 most appropriate here */
119 return PyLong_FromVoidPtr((void*)handle);
122 /* Console I/O */
124 static PyObject *
125 msvcrt_kbhit(PyObject *self, PyObject *args)
127 int ok;
129 if (!PyArg_ParseTuple(args, ":kbhit"))
130 return NULL;
132 ok = _kbhit();
133 return PyInt_FromLong(ok);
136 static PyObject *
137 msvcrt_getch(PyObject *self, PyObject *args)
139 int ch;
140 char s[1];
142 if (!PyArg_ParseTuple(args, ":getch"))
143 return NULL;
145 Py_BEGIN_ALLOW_THREADS
146 ch = _getch();
147 Py_END_ALLOW_THREADS
148 s[0] = ch;
149 return PyString_FromStringAndSize(s, 1);
152 #ifdef _WCONIO_DEFINED
153 static PyObject *
154 msvcrt_getwch(PyObject *self, PyObject *args)
156 Py_UNICODE ch;
157 Py_UNICODE u[1];
159 if (!PyArg_ParseTuple(args, ":getwch"))
160 return NULL;
162 Py_BEGIN_ALLOW_THREADS
163 ch = _getwch();
164 Py_END_ALLOW_THREADS
165 u[0] = ch;
166 return PyUnicode_FromUnicode(u, 1);
168 #endif
170 static PyObject *
171 msvcrt_getche(PyObject *self, PyObject *args)
173 int ch;
174 char s[1];
176 if (!PyArg_ParseTuple(args, ":getche"))
177 return NULL;
179 Py_BEGIN_ALLOW_THREADS
180 ch = _getche();
181 Py_END_ALLOW_THREADS
182 s[0] = ch;
183 return PyString_FromStringAndSize(s, 1);
186 #ifdef _WCONIO_DEFINED
187 static PyObject *
188 msvcrt_getwche(PyObject *self, PyObject *args)
190 Py_UNICODE ch;
191 Py_UNICODE s[1];
193 if (!PyArg_ParseTuple(args, ":getwche"))
194 return NULL;
196 Py_BEGIN_ALLOW_THREADS
197 ch = _getwche();
198 Py_END_ALLOW_THREADS
199 s[0] = ch;
200 return PyUnicode_FromUnicode(s, 1);
202 #endif
204 static PyObject *
205 msvcrt_putch(PyObject *self, PyObject *args)
207 char ch;
209 if (!PyArg_ParseTuple(args, "c:putch", &ch))
210 return NULL;
212 _putch(ch);
213 Py_INCREF(Py_None);
214 return Py_None;
217 #ifdef _WCONIO_DEFINED
218 static PyObject *
219 msvcrt_putwch(PyObject *self, PyObject *args)
221 Py_UNICODE *ch;
222 int size;
224 if (!PyArg_ParseTuple(args, "u#:putwch", &ch, &size))
225 return NULL;
227 if (size == 0) {
228 PyErr_SetString(PyExc_ValueError,
229 "Expected unicode string of length 1");
230 return NULL;
232 _putwch(*ch);
233 Py_RETURN_NONE;
236 #endif
238 static PyObject *
239 msvcrt_ungetch(PyObject *self, PyObject *args)
241 char ch;
243 if (!PyArg_ParseTuple(args, "c:ungetch", &ch))
244 return NULL;
246 if (_ungetch(ch) == EOF)
247 return PyErr_SetFromErrno(PyExc_IOError);
248 Py_INCREF(Py_None);
249 return Py_None;
252 #ifdef _WCONIO_DEFINED
253 static PyObject *
254 msvcrt_ungetwch(PyObject *self, PyObject *args)
256 Py_UNICODE ch;
258 if (!PyArg_ParseTuple(args, "u:ungetwch", &ch))
259 return NULL;
261 if (_ungetch(ch) == EOF)
262 return PyErr_SetFromErrno(PyExc_IOError);
263 Py_INCREF(Py_None);
264 return Py_None;
266 #endif
268 static void
269 insertint(PyObject *d, char *name, int value)
271 PyObject *v = PyInt_FromLong((long) value);
272 if (v == NULL) {
273 /* Don't bother reporting this error */
274 PyErr_Clear();
276 else {
277 PyDict_SetItemString(d, name, v);
278 Py_DECREF(v);
283 /* List of functions exported by this module */
284 static struct PyMethodDef msvcrt_functions[] = {
285 {"heapmin", msvcrt_heapmin, METH_VARARGS},
286 {"locking", msvcrt_locking, METH_VARARGS},
287 {"setmode", msvcrt_setmode, METH_VARARGS},
288 {"open_osfhandle", msvcrt_open_osfhandle, METH_VARARGS},
289 {"get_osfhandle", msvcrt_get_osfhandle, METH_VARARGS},
290 {"kbhit", msvcrt_kbhit, METH_VARARGS},
291 {"getch", msvcrt_getch, METH_VARARGS},
292 {"getche", msvcrt_getche, METH_VARARGS},
293 {"putch", msvcrt_putch, METH_VARARGS},
294 {"ungetch", msvcrt_ungetch, METH_VARARGS},
295 #ifdef _WCONIO_DEFINED
296 {"getwch", msvcrt_getwch, METH_VARARGS},
297 {"getwche", msvcrt_getwche, METH_VARARGS},
298 {"putwch", msvcrt_putwch, METH_VARARGS},
299 {"ungetwch", msvcrt_ungetwch, METH_VARARGS},
300 #endif
301 {NULL, NULL}
304 PyMODINIT_FUNC
305 initmsvcrt(void)
307 int st;
308 PyObject *d;
309 PyObject *m = Py_InitModule("msvcrt", msvcrt_functions);
310 if (m == NULL)
311 return;
312 d = PyModule_GetDict(m);
314 /* constants for the locking() function's mode argument */
315 insertint(d, "LK_LOCK", _LK_LOCK);
316 insertint(d, "LK_NBLCK", _LK_NBLCK);
317 insertint(d, "LK_NBRLCK", _LK_NBRLCK);
318 insertint(d, "LK_RLCK", _LK_RLCK);
319 insertint(d, "LK_UNLCK", _LK_UNLCK);
321 /* constants for the crt versions */
322 #ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN
323 st = PyModule_AddStringConstant(m, "VC_ASSEMBLY_PUBLICKEYTOKEN",
324 _VC_ASSEMBLY_PUBLICKEYTOKEN);
325 if (st < 0)return;
326 #endif
327 #ifdef _CRT_ASSEMBLY_VERSION
328 st = PyModule_AddStringConstant(m, "CRT_ASSEMBLY_VERSION",
329 _CRT_ASSEMBLY_VERSION);
330 if (st < 0)return;
331 #endif
332 #ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX
333 st = PyModule_AddStringConstant(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",
334 __LIBRARIES_ASSEMBLY_NAME_PREFIX);
335 if (st < 0)return;
336 #endif