use warnings; use Inline C => Config => LIBS => '-lSetupAPI', BUILD_NOISY => 1; use Inline C => <<'EOC'; #include #include #include #include #include int wrap_SetupDiGetClassDevs() { HDEVINFO hDevInfo; // Create a HDEVINFO with all present devices. hDevInfo = SetupDiGetClassDevs(NULL, 0, // Enumerator 0, DIGCF_PRESENT | DIGCF_ALLCLASSES ); if (hDevInfo == INVALID_HANDLE_VALUE) croak("INVALID_HANDLE_VALUE returned"); return hDevInfo; } void wrap_SetupDiDestroyDeviceInfoList(int hDevInfo) { SetupDiDestroyDeviceInfoList(hDevInfo); } void foo(int hDevInfo) { INLINE_STACK_VARS; SP_DEVINFO_DATA DeviceInfoData; DWORD i, DataT, buffersize; LPTSTR buffer; // Enumerate through all devices in Set. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); INLINE_STACK_RESET; for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i, &DeviceInfoData);i++) { buffer = NULL; buffersize = 0; // // Call function with null to begin with, // then use the returned buffer size // to Alloc the buffer. Keep calling until // success or an unknown failure. // while (!SetupDiGetDeviceRegistryProperty( hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buffer, buffersize, &buffersize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // Change the buffer size. if (buffer) LocalFree(buffer); buffer = LocalAlloc(LPTR,buffersize); } else croak("ERROR 1 in sub foo"); } INLINE_STACK_PUSH(sv_2mortal(newSVpv(buffer, 0))); if (buffer) LocalFree(buffer); } if ( GetLastError()!=NO_ERROR && GetLastError()!=ERROR_NO_MORE_ITEMS ) croak("ERROR 2 in sub foo"); INLINE_STACK_DONE; INLINE_STACK_RETURN(i); } EOC # perl code starts here: my $handle = wrap_SetupDiGetClassDevs(); my @devices = foo($handle); # clean up wrap_SetupDiDestroyDeviceInfoList($handle); print $_, "\n" for @devices;