From deb72df0777f9a59b3b019adeccbba6b31a89361 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 18 Jan 2016 12:18:48 +0530 Subject: [PATCH] Remove code superseeded by winusb --- setup/extensions.py | 2 +- src/calibre/utils/windows/winutil.c | 636 ---------------------------- 2 files changed, 1 insertion(+), 637 deletions(-) diff --git a/setup/extensions.py b/setup/extensions.py index aec17e1d4d..5e7f511672 100644 --- a/setup/extensions.py +++ b/setup/extensions.py @@ -275,7 +275,7 @@ if iswindows: extensions.extend([ Extension('winutil', ['calibre/utils/windows/winutil.c'], - libraries=['shell32', 'setupapi', 'wininet'], + libraries=['shell32', 'wininet'], cflags=['/X'] ), Extension('wpd', diff --git a/src/calibre/utils/windows/winutil.c b/src/calibre/utils/windows/winutil.c index 97f5ccd6c1..1339825e08 100644 --- a/src/calibre/utils/windows/winutil.c +++ b/src/calibre/utils/windows/winutil.c @@ -13,24 +13,6 @@ system. It should be compiled with the same version of VisualStudio used to compile python. It hasn't been tested with MinGW. We try to use unicode wherever possible in this module. -.. exception:: winutil.DriveError - Raised when scanning for mounted volumes fails. - -.. function:: is_usb_device_connected(vid : integer, pid : integer) -> bool - Return `True` iff the USB device identified by the VendorID `vid` and - ProductID `pid` is connected to the system. - -.. function:: get_usb_devices() -> list of lowercase strings - Return a list of all USB devices connected to the system. Each - device is represented by a lowercase unicode string whoose format is - the windows *Device Identifier* format. See the MSDN documentation. - -.. function:: get_mounted_volumes_for_usb_device(vid : integer, pid : integer) -> dictionary - Return a dictionary of the form `volume_id`:`drive_letter` for all - volumes mounted from the device specified by `vid` and `pid`. - - :raises: :exception:`winutil.DriveError` if scanning fails. - .. function:: special_folder_path(csidl_id) -> path Get paths to common system folders. See windows documentation of SHGetFolderPath. @@ -77,7 +59,6 @@ wherever possible in this module. #define BUFSIZE 512 #define MAX_DRIVES 26 -static PyObject *DriveError; static BOOL DEBUG = FALSE; //#define debug(fmt, ...) if DEBUG printf(x, __VA_ARGS__); @@ -89,12 +70,6 @@ debug(const char *fmt, ...) { va_end(argList); } -struct tagDrives -{ - WCHAR letter; - WCHAR volume[BUFSIZE]; -}; - static void console_out(LPCWSTR fmt, LPCWSTR arg) { char *bfmt, *barg; int sz; @@ -187,593 +162,6 @@ winutil_set_debug(PyObject *self, PyObject *args) { return Py_None; } -/* Obsolete device code {{{ */ -static LPWSTR -get_registry_property(HDEVINFO hDevInfo, DWORD index, DWORD property, BOOL *iterate) { - /* Get the property specified by `property` from the registry for the - * device enumerated by `index` in the collection `hDevInfo`. `iterate` - * will be set to `FALSE` if `index` points outside `hDevInfo`. - * :return: A string allocated on the heap containing the property or - * `NULL` if an error occurred. - */ - SP_DEVINFO_DATA DeviceInfoData; - DWORD DataT; - LPWSTR buffer = NULL; - DWORD buffersize = 0; - DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - if (!SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData)) { - *iterate = FALSE; - return NULL; - } - - while(!SetupDiGetDeviceRegistryPropertyW( - hDevInfo, - &DeviceInfoData, - property, - &DataT, - (PBYTE)buffer, - buffersize, - &buffersize)) { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (buffer != NULL) { PyMem_Free(buffer); buffer = NULL; } - buffer = (LPWSTR)PyMem_Malloc(2*buffersize); // Twice for bug in Win2k - } else { - if (buffer != NULL) { PyMem_Free(buffer); buffer = NULL; } - PyErr_SetFromWindowsErr(0); - break; - } - } //while - - return buffer; -} - -static BOOL -check_device_id(LPWSTR buffer, unsigned int vid, unsigned int pid) { - WCHAR xVid[9], dVid[9], xPid[9], dPid[9]; - unsigned int j; - _snwprintf_s(xVid, 9, _TRUNCATE, L"vid_%4.4x", vid); - _snwprintf_s(dVid, 9, _TRUNCATE, L"vid_%4.4d", vid); - _snwprintf_s(xPid, 9, _TRUNCATE, L"pid_%4.4x", pid); - _snwprintf_s(dPid, 9, _TRUNCATE, L"pid_%4.4d", pid); - - for (j = 0; j < wcslen(buffer); j++) buffer[j] = tolower(buffer[j]); - - return ( (wcsstr(buffer, xVid) != NULL || wcsstr(buffer, dVid) != NULL ) && - (wcsstr(buffer, xPid) != NULL || wcsstr(buffer, dPid) != NULL ) - ); -} - -static HDEVINFO -create_device_info_set(LPGUID guid, PCTSTR enumerator, HWND parent, DWORD flags) { - HDEVINFO hDevInfo; - hDevInfo = SetupDiGetClassDevs( - guid, - enumerator, - parent, - flags - ); - if (hDevInfo == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - } - return hDevInfo; -} - -int n; - -BOOL -get_all_removable_disks(struct tagDrives *g_drives) -{ - WCHAR caDrive[4]; - WCHAR volume[BUFSIZE]; - int nLoopIndex; - DWORD dwDriveMask; - unsigned int g_count=0; - - - caDrive[0] = 'A'; - caDrive[1] = ':'; - caDrive[2] = '\\'; - caDrive[3] = 0; - - - - - - // Get all drives in the system. - dwDriveMask = GetLogicalDrives(); - - - if(dwDriveMask == 0) - { - PyErr_SetString(DriveError, "GetLogicalDrives failed"); - return FALSE; - } - - - // Loop for all drives (MAX_DRIVES = 26) - - - for(nLoopIndex = 0; nLoopIndex < MAX_DRIVES; nLoopIndex++) - { - // if a drive is present (we cannot ignore the A and B drives as there - // are people out there that think mapping devices to use those letters - // is a good idea, sigh) - if(dwDriveMask & 1) - { - caDrive[0] = 'A' + nLoopIndex; - - - // If a drive is removable - if(GetDriveType(caDrive) == DRIVE_REMOVABLE) - { - //Get its volume info and store it in the global variable. - if(GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFSIZE)) - { - g_drives[g_count].letter = caDrive[0]; - wcscpy_s(g_drives[g_count].volume, BUFSIZE, volume); - g_count ++; - } - - } - } - dwDriveMask >>= 1; - } - - - // success if atleast one removable drive is found. - if(g_count == 0) - { - PyErr_SetString(DriveError, "No removable drives found"); - return FALSE; - } - return TRUE; - -} - -static DEVINST -GetDrivesDevInstByDeviceNumber(long DeviceNumber, - UINT DriveType, LPWSTR szDosDeviceName) -{ - GUID *guid; - HDEVINFO hDevInfo; - DWORD dwIndex, dwBytesReturned; - BOOL bRet, IsFloppy; - BYTE Buf[1024]; - PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd; - long res; - HANDLE hDrive; - STORAGE_DEVICE_NUMBER sdn; - SP_DEVICE_INTERFACE_DATA spdid; - SP_DEVINFO_DATA spdd; - DWORD dwSize; - - - IsFloppy = (wcsstr(szDosDeviceName, L"\\Floppy") != NULL); // is there a better way? - - switch (DriveType) { - case DRIVE_REMOVABLE: - if ( IsFloppy ) { - guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY; - } else { - guid = (GUID*)&GUID_DEVINTERFACE_DISK; - } - break; - case DRIVE_FIXED: - guid = (GUID*)&GUID_DEVINTERFACE_DISK; - break; - case DRIVE_CDROM: - guid = (GUID*)&GUID_DEVINTERFACE_CDROM; - break; - default: - PyErr_SetString(PyExc_ValueError, "Invalid drive type"); - return 0; - } - - // Get device interface info set handle - // for all devices attached to system - hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, - DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - - if (hDevInfo == INVALID_HANDLE_VALUE) { - PyErr_SetString(PyExc_ValueError, "Invalid handle value"); - return 0; - } - - // Retrieve a context structure for a device interface - // of a device information set. - dwIndex = 0; - bRet = FALSE; - - - pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf; - spdid.cbSize = sizeof(spdid); - - while ( TRUE ) { - bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, - guid, dwIndex, &spdid); - if ( !bRet ) { - break; - } - - dwSize = 0; - SetupDiGetDeviceInterfaceDetail(hDevInfo, - &spdid, NULL, 0, &dwSize, NULL); - - if ( dwSize!=0 && dwSize<=sizeof(Buf) ) { - pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes! - - ZeroMemory((PVOID)&spdd, sizeof(spdd)); - spdd.cbSize = sizeof(spdd); - - res = - SetupDiGetDeviceInterfaceDetail(hDevInfo, & - spdid, pspdidd, - dwSize, &dwSize, - &spdd); - if ( res ) { - hDrive = CreateFile(pspdidd->DevicePath,0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if ( hDrive != INVALID_HANDLE_VALUE ) { - dwBytesReturned = 0; - res = DeviceIoControl(hDrive, - IOCTL_STORAGE_GET_DEVICE_NUMBER, - NULL, 0, &sdn, sizeof(sdn), - &dwBytesReturned, NULL); - if ( res ) { - if ( DeviceNumber == (long)sdn.DeviceNumber ) { - CloseHandle(hDrive); - SetupDiDestroyDeviceInfoList(hDevInfo); - return spdd.DevInst; - } - } - CloseHandle(hDrive); - } - } - } - dwIndex++; - } - - SetupDiDestroyDeviceInfoList(hDevInfo); - PyErr_SetString(PyExc_ValueError, "Invalid device number"); - - return 0; -} - - - -static BOOL -eject_drive_letter(WCHAR DriveLetter) { - LPWSTR szRootPath = L"X:\\", - szDevicePath = L"X:", - szVolumeAccessPath = L"\\\\.\\X:"; - WCHAR szDosDeviceName[MAX_PATH]; - long DeviceNumber, res, tries; - HANDLE hVolume; - STORAGE_DEVICE_NUMBER sdn; - DWORD dwBytesReturned; - DEVINST DevInst; - ULONG Status; - ULONG ProblemNumber; - UINT DriveType; - PNP_VETO_TYPE VetoType; - WCHAR VetoNameW[MAX_PATH]; - BOOL bSuccess; - DEVINST DevInstParent; - - szRootPath[0] = DriveLetter; - szDevicePath[0] = DriveLetter; - szVolumeAccessPath[4] = DriveLetter; - - DeviceNumber = -1; - - hVolume = CreateFileW(szVolumeAccessPath, 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hVolume == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - return FALSE; - } - - dwBytesReturned = 0; - res = DeviceIoControl(hVolume, - IOCTL_STORAGE_GET_DEVICE_NUMBER, - NULL, 0, &sdn, sizeof(sdn), - &dwBytesReturned, NULL); - if ( res ) { - DeviceNumber = sdn.DeviceNumber; - } - CloseHandle(hVolume); - - if ( DeviceNumber == -1 ) { - PyErr_SetString(PyExc_ValueError, "Can't find drive number"); - return FALSE; - } - - res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH); - if ( !res ) { - PyErr_SetString(PyExc_ValueError, "Can't find dos device"); - return FALSE; - } - - DriveType = GetDriveType(szRootPath); - - DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, - DriveType, szDosDeviceName); - if (DevInst == 0) return FALSE; - - DevInstParent = 0; - Status = 0; - ProblemNumber = 0; - bSuccess = FALSE; - - res = CM_Get_Parent(&DevInstParent, DevInst, 0); - - for ( tries = 0; tries < 3; tries++ ) { - VetoNameW[0] = 0; - - res = CM_Request_Device_EjectW(DevInstParent, - &VetoType, VetoNameW, MAX_PATH, 0); - - bSuccess = (res==CR_SUCCESS && - VetoType==PNP_VetoTypeUnknown); - if ( bSuccess ) { - break; - } - - Sleep(500); // required to give the next tries a chance! - } - if (!bSuccess) PyErr_SetString(PyExc_ValueError, "Failed to eject drive after three tries"); - return bSuccess; -} - -static PyObject * -winutil_eject_drive(PyObject *self, PyObject *args) { - char letter = '0'; - WCHAR DriveLetter = L'0'; - - if (!PyArg_ParseTuple(args, "c", &letter)) return NULL; - - if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, &letter, 1, &DriveLetter, 1) == 0) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - - if (!eject_drive_letter(DriveLetter)) return NULL; - Py_RETURN_NONE; -} - - -PSP_DEVICE_INTERFACE_DETAIL_DATA -get_device_ancestors(HDEVINFO hDevInfo, DWORD index, PyObject *candidates, BOOL *iterate, BOOL ddebug) { - SP_DEVICE_INTERFACE_DATA interfaceData; - SP_DEVINFO_DATA devInfoData; - BOOL status; - PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData; - DWORD interfaceDetailDataSize, - reqSize; - DEVINST parent, pos; - wchar_t temp[BUFSIZE]; - int i; - PyObject *devid; - - interfaceData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA); - devInfoData.cbSize = sizeof (SP_DEVINFO_DATA); - - status = SetupDiEnumDeviceInterfaces ( - hDevInfo, // Interface Device Info handle - NULL, // Device Info data - (LPGUID)&GUID_DEVINTERFACE_VOLUME, // Interface registered by driver - index, // Member - &interfaceData // Device Interface Data - ); - if ( status == FALSE ) { - *iterate = FALSE; - return NULL; - } - SetupDiGetDeviceInterfaceDetail ( - hDevInfo, // Interface Device info handle - &interfaceData, // Interface data for the event class - NULL, // Checking for buffer size - 0, // Checking for buffer size - &reqSize, // Buffer size required to get the detail data - NULL // Checking for buffer size - ); - - interfaceDetailDataSize = reqSize; - interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)PyMem_Malloc(interfaceDetailDataSize+50); - if ( interfaceDetailData == NULL ) { - PyErr_NoMemory(); - return NULL; - } - interfaceDetailData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA); - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - status = SetupDiGetDeviceInterfaceDetail ( - hDevInfo, // Interface Device info handle - &interfaceData, // Interface data for the event class - interfaceDetailData, // Interface detail data - interfaceDetailDataSize, // Interface detail data size - &reqSize, // Buffer size required to get the detail data - &devInfoData); // Interface device info - if (ddebug) printf("Getting ancestors\n"); fflush(stdout); - - if ( status == FALSE ) {PyErr_SetFromWindowsErr(0); PyMem_Free(interfaceDetailData); return NULL;} - - pos = devInfoData.DevInst; - - for(i = 0; i < 10; i++) { - // Get the device instance of parent. - if (CM_Get_Parent(&parent, pos, 0) != CR_SUCCESS) break; - if (CM_Get_Device_ID(parent, temp, BUFSIZE, 0) == CR_SUCCESS) { - if (ddebug) console_out(L"device id: %s\n", temp); - devid = PyUnicode_FromWideChar(temp, wcslen(temp)); - if (devid) { - PyList_Append(candidates, devid); - Py_DECREF(devid); - } - } - pos = parent; - } - - return interfaceDetailData; -} - -static PyObject * -winutil_get_removable_drives(PyObject *self, PyObject *args) { - HDEVINFO hDevInfo; - BOOL iterate = TRUE, ddebug = FALSE; - PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData; - DWORD i; - unsigned int j; - size_t length; - WCHAR volume[BUFSIZE]; - struct tagDrives g_drives[MAX_DRIVES]; - PyObject *volumes, *key, *candidates, *pdebug = Py_False, *temp; - - if (!PyArg_ParseTuple(args, "|O", &pdebug)) { - return NULL; - } - - // Find all removable drives - for (j = 0; j < MAX_DRIVES; j++) g_drives[j].letter = 0; - if (!get_all_removable_disks(g_drives)) return NULL; - - volumes = PyDict_New(); - if (volumes == NULL) return PyErr_NoMemory(); - ddebug = PyObject_IsTrue(pdebug); - - hDevInfo = create_device_info_set((LPGUID)&GUID_DEVINTERFACE_VOLUME, - NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (hDevInfo == INVALID_HANDLE_VALUE) { Py_DECREF(volumes); return NULL; } - - // Enumerate through the set - for (i=0; iterate; i++) { - candidates = PyList_New(0); - if (candidates == NULL) { Py_DECREF(volumes); return PyErr_NoMemory();} - - interfaceDetailData = get_device_ancestors(hDevInfo, i, candidates, &iterate, ddebug); - if (interfaceDetailData == NULL) { - PyErr_Print(); - Py_DECREF(candidates); candidates = NULL; - continue; - } - - length = wcslen(interfaceDetailData->DevicePath); - interfaceDetailData->DevicePath[length] = L'\\'; - interfaceDetailData->DevicePath[length+1] = 0; - - if (ddebug) console_out(L"Device path: %s\n", interfaceDetailData->DevicePath); - // On Vista+ DevicePath contains the information we need. - temp = PyUnicode_FromWideChar(interfaceDetailData->DevicePath, length); - if (temp == NULL) return PyErr_NoMemory(); - PyList_Append(candidates, temp); - Py_DECREF(temp); - if(GetVolumeNameForVolumeMountPointW(interfaceDetailData->DevicePath, volume, BUFSIZE)) { - if (ddebug) console_out(L"Volume: %s\n", volume); - - for(j = 0; j < MAX_DRIVES; j++) { - if(g_drives[j].letter != 0 && wcscmp(g_drives[j].volume, volume)==0) { - if (ddebug) printf("Found drive: %c\n", (char)g_drives[j].letter); fflush(stdout); - key = PyBytes_FromFormat("%c", (char)g_drives[j].letter); - if (key == NULL) return PyErr_NoMemory(); - PyDict_SetItem(volumes, key, candidates); - Py_DECREF(key); key = NULL; - break; - } - } - - } - Py_XDECREF(candidates); candidates = NULL; - PyMem_Free(interfaceDetailData); - } //for - - SetupDiDestroyDeviceInfoList(hDevInfo); - return volumes; -} - -static PyObject * -winutil_get_usb_devices(PyObject *self, PyObject *args) { - unsigned int j; - size_t buffersize; - HDEVINFO hDevInfo; - DWORD i; BOOL iterate = TRUE; - PyObject *devices, *temp = (PyObject *)1; - LPWSTR buffer; - BOOL ok = 1; - - if (!PyArg_ParseTuple(args, "")) return NULL; - - devices = PyList_New(0); - if (devices == NULL) {PyErr_NoMemory(); return NULL;} - - // Create a Device information set with all USB devices - hDevInfo = create_device_info_set(NULL, L"USB", 0, - DIGCF_PRESENT | DIGCF_ALLCLASSES); - if (hDevInfo == INVALID_HANDLE_VALUE) { - Py_DECREF(devices); - return NULL; - } - // Enumerate through the set - for (i=0; iterate; i++) { - buffer = get_registry_property(hDevInfo, i, SPDRP_HARDWAREID, &iterate); - if (buffer == NULL) { - PyErr_Print(); continue; - } - buffersize = wcslen(buffer); - for (j = 0; j < buffersize; j++) buffer[j] = towlower(buffer[j]); - temp = PyUnicode_FromWideChar(buffer, buffersize); - PyMem_Free(buffer); - if (temp == NULL) { - PyErr_NoMemory(); - ok = 0; - break; - } - PyList_Append(devices, temp); Py_DECREF(temp); temp = NULL; - } //for - if (!ok) { Py_DECREF(devices); devices = NULL; } - SetupDiDestroyDeviceInfoList(hDevInfo); - return devices; -} - - -static PyObject * -winutil_is_usb_device_connected(PyObject *self, PyObject *args) { - unsigned int vid, pid; - HDEVINFO hDevInfo; - DWORD i; BOOL iterate = TRUE; - LPWSTR buffer; - int found = FALSE; - PyObject *ans; - - if (!PyArg_ParseTuple(args, "ii", &vid, &pid)) { - return NULL; - } - - // Create a Device information set with all USB devices - hDevInfo = create_device_info_set(NULL, L"USB", 0, - DIGCF_PRESENT | DIGCF_ALLCLASSES); - if (hDevInfo == INVALID_HANDLE_VALUE) - return NULL; - - // Enumerate through the set - for (i=0; iterate && !found; i++) { - buffer = get_registry_property(hDevInfo, i, SPDRP_HARDWAREID, &iterate); - if (buffer == NULL) { - PyErr_Print(); continue; - } - found = check_device_id(buffer, vid, pid); - PyMem_Free(buffer); - } // for - - SetupDiDestroyDeviceInfoList(hDevInfo); - ans = (found) ? Py_True : Py_False; - Py_INCREF(ans); - return ans; -} -/* }}} */ - static int gettmarg(PyObject *args, struct tm *p) { @@ -951,23 +339,6 @@ static PyMethodDef WinutilMethods[] = { "script being run. So to replace sys.argv, you should use " "sys.argv[1:] = argv()[1:]."}, - {"is_usb_device_connected", winutil_is_usb_device_connected, METH_VARARGS, - "is_usb_device_connected(vid, pid) -> bool\n\n" - "Check if the USB device identified by VendorID: vid (integer) and" - " ProductID: pid (integer) is currently connected."}, - - {"get_usb_devices", winutil_get_usb_devices, METH_VARARGS, - "get_usb_devices() -> list of strings\n\n" - "Return a list of the hardware IDs of all USB devices " - "connected to the system."}, - - {"get_removable_drives", winutil_get_removable_drives, METH_VARARGS, - "get_removable_drives(debug=False) -> dict\n\n" - "Return mapping of all removable drives in the system. Maps drive letters " - "to a list of device id strings, atleast one of which will carry the information " - "needed for device matching. On Vista+ it is always the last string in the list. " - "Note that you should upper case all strings."}, - {"set_debug", winutil_set_debug, METH_VARARGS, "set_debug(bool)\n\nSet debugging mode." }, @@ -981,10 +352,6 @@ is not present, current time as returned by localtime() is used. format must\n\ be a unicode string. Returns unicode strings." }, - {"eject_drive", winutil_eject_drive, METH_VARARGS, - "eject_drive(drive_letter)\n\nEject a drive. Raises an exception on failure." - }, - {"internet_connected", winutil_internet_connected, METH_VARARGS, "internet_connected()\n\nReturn True if there is an active internet connection" }, @@ -1003,9 +370,6 @@ initwinutil(void) { "Defines utility methods to interface with windows." ); if (m == NULL) return; - DriveError = PyErr_NewException("winutil.DriveError", NULL, NULL); - if (DriveError == NULL) return; - PyModule_AddObject(m, "DriveError", DriveError); PyModule_AddIntConstant(m, "CSIDL_ADMINTOOLS", CSIDL_ADMINTOOLS); PyModule_AddIntConstant(m, "CSIDL_APPDATA", CSIDL_APPDATA);