00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022
00023 #include <iostream>
00024 #include <sstream>
00025
00026
00027 #ifdef LIBSMBIOS_WIN_USE_WMI
00028 # ifndef _WIN32_DCOM
00029 # define _WIN32_DCOM
00030 # endif
00031
00032
00033
00034 # pragma comment(lib, "wbemuuid")
00035
00036 # include <objbase.h>
00037 # include <wbemcli.h>
00038 #endif
00039
00040 #include "smbios/IMemory.h"
00041 #include "SmbiosImpl.h"
00042 #include "miniddk.h"
00043
00044
00045 #include "smbios/message.h"
00046
00047 using namespace smbiosLowlevel;
00048 using namespace std;
00049
00050 namespace smbios
00051 {
00052
00053 GetSystemFirmwareTablePtr GetSystemFirmwareTable = 0;
00054
00055 int LoadNtdllFuncs(void)
00056 {
00057 HMODULE hKerneldll;
00058
00059 hKerneldll = GetModuleHandle( L"kernel32.dll" );
00060 if (!hKerneldll)
00061 return FALSE;
00062
00063
00064
00065 GetSystemFirmwareTable = (GetSystemFirmwareTablePtr) GetProcAddress(hKerneldll, "GetSystemFirmwareTable");
00066
00067 return TRUE;
00068 }
00069
00070
00071 bool SmbiosWinGetFirmwareTableStrategy::getSmbiosTable(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point *table_header, bool )
00072 {
00073
00074 u8 *newSmbiosBuffer = 0;
00075
00076 DWORD iSignature = 'R';
00077 iSignature = iSignature << 8 | 'S';
00078 iSignature = iSignature << 8 | 'M';
00079 iSignature = iSignature << 8 | 'B';
00080
00081 if( !GetSystemFirmwareTable )
00082 if( !LoadNtdllFuncs() )
00083 throw ParseExceptionImpl( _("Could not load dll functions.") );
00084
00085 if( !GetSystemFirmwareTable )
00086 throw ParseExceptionImpl( _("Could not access GetSystemFirmwareTable() API.") );
00087
00088 int iBufferSizeNeeded = GetSystemFirmwareTable( iSignature, 0, 0, 0 );
00089 if( iBufferSizeNeeded <= 0 )
00090 throw ParseExceptionImpl( _("GetSystemFirmwareTable returned 0 for table length.") );
00091
00092 newSmbiosBuffer = new u8[iBufferSizeNeeded];
00093 if( ! newSmbiosBuffer )
00094 throw ParseExceptionImpl( _("Failed to allocate memory for Firmware table.") );
00095 memset( newSmbiosBuffer, 0, sizeof(u8) * iBufferSizeNeeded );
00096
00097
00098
00099
00100
00101
00102
00103
00104 GetSystemFirmwareTable( iSignature, 0, newSmbiosBuffer, iBufferSizeNeeded );
00105
00106
00107 table_header->table_length = static_cast<u16>(iBufferSizeNeeded);
00108 table_header->major_ver = newSmbiosBuffer[1];
00109 table_header->minor_ver = newSmbiosBuffer[2];
00110 table_header->table_num_structs = 9999;
00111
00112
00113 # define MS_RSMB_HEADER_SIZE 8
00114
00115 memmove(newSmbiosBuffer, newSmbiosBuffer + MS_RSMB_HEADER_SIZE, iBufferSizeNeeded - MS_RSMB_HEADER_SIZE);
00116 memset( newSmbiosBuffer + iBufferSizeNeeded - MS_RSMB_HEADER_SIZE, 0, MS_RSMB_HEADER_SIZE);
00117
00118
00119 if( *smbiosBuffer )
00120 {
00121 memset (const_cast<u8 *>(*smbiosBuffer), 0, sizeof (**smbiosBuffer));
00122 delete [] const_cast<u8 *>(*smbiosBuffer);
00123 *smbiosBuffer = 0;
00124 }
00125
00126 *smbiosBuffer = (const u8 *) newSmbiosBuffer;
00127 return true;
00128 }
00129
00130
00131
00132 #ifdef LIBSMBIOS_WIN_USE_WMI
00133
00134 static void GetWMISMBIOSEntry( IWbemClassObject **pSmbios )
00135 {
00136 BSTR path = SysAllocString(L"root\\wmi");
00137 BSTR className = SysAllocString(L"MSSmBios_RawSMBiosTables");
00138 ULONG uReturned = 1;
00139 HRESULT hr = S_FALSE;
00140 IWbemLocator *pLocator = NULL;
00141 IWbemServices *pNamespace = NULL;
00142 IEnumWbemClassObject *pEnumSMBIOS = NULL;
00143
00144 try
00145 {
00146 hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE,
00147 NULL, EOAC_SECURE_REFS, NULL );
00148
00149
00150
00151
00152
00153 hr = CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLocator );
00154
00155 if (! SUCCEEDED( hr ) )
00156 throw InternalErrorImpl(_("CoCreateInstance() failed for locator. "
00157 "Check that the security levels have been "
00158 "properly initialized."
00159 ));
00160
00161 hr = pLocator->ConnectServer(path, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace );
00162 pLocator->Release();
00163
00164 if( WBEM_S_NO_ERROR != hr )
00165 throw InternalErrorImpl(_("ConnectServer() failed for namespace"));
00166
00167 hr = pNamespace->CreateInstanceEnum( className, 0, NULL, &pEnumSMBIOS );
00168 pNamespace->Release();
00169
00170 if (! SUCCEEDED( hr ) )
00171 throw InternalErrorImpl(_("CreateInstanceEnum() failed for MSSmBios_RawSMBiosTables"));
00172
00173 hr = pEnumSMBIOS->Next( 4000, 1, pSmbios, &uReturned );
00174 pEnumSMBIOS->Release();
00175
00176 if ( 1 != uReturned )
00177 throw InternalErrorImpl(_("Next() failed for pEnumSMBIOS"));
00178 }
00179 catch(const exception &)
00180 {
00181 SysFreeString(className);
00182 SysFreeString(path);
00183 throw;
00184 }
00185 }
00186
00187
00188 static void GetWMISMBIOSTable( IWbemClassObject *pSmbios, WMISMBIOSINFO &smbiosData )
00189 {
00190 BSTR propName;
00191 CIMTYPE type;
00192 VARIANT pVal;
00193 SAFEARRAY *parray = NULL;
00194
00195 if ( NULL == pSmbios )
00196 throw ParseExceptionImpl( _("GetWMISMBIOSTable: NULL pointer to SMBIOS Entry specified.") );
00197
00198 VariantInit(&pVal);
00199
00200 propName = SysAllocString(L"SMBiosData");
00201 pSmbios->Get( propName, 0L, &pVal, &type, NULL);
00202 SysFreeString(propName);
00203
00204 if ( ( VT_UI1 | VT_ARRAY ) != pVal.vt )
00205 throw ParseExceptionImpl( _("GetWMISMBIOSTable: SMBiosData returned unknown entry type.") );
00206
00207 parray = V_ARRAY(&pVal);
00208
00209 smbiosData.bufferSize = parray->rgsabound[0].cElements;
00210
00211 if ( smbiosData.bufferSize == 0 )
00212 throw ParseExceptionImpl( _("GetWMISMBIOSTable: Buffer size was zero.") );
00213
00214 smbiosData.buffer = new u8[smbiosData.bufferSize];
00215 if ( ! smbiosData.buffer )
00216 throw ParseExceptionImpl( _("GetWMISMBIOSTable: Failed to allocate memory for SMBIOS table.") );
00217
00218 memcpy(smbiosData.buffer, (u8 *)parray->pvData, smbiosData.bufferSize);
00219 }
00220
00221 static void GetWMISMBIOSVersion( IWbemClassObject *pSmbios, u8 *majorVersion, u8 *minorVersion )
00222 {
00223 BSTR propName;
00224 HRESULT hr = S_OK;
00225 CIMTYPE type;
00226 VARIANT pVal;
00227
00228 if ( NULL == pSmbios )
00229 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: null pointer passed as pSmbios.") );
00230
00231 VariantInit( &pVal );
00232 propName = SysAllocString( L"SmbiosMajorVersion" );
00233 hr = pSmbios->Get( propName, 0L, &pVal, &type, NULL );
00234 SysFreeString( propName );
00235
00236 if ( ! SUCCEEDED( hr ) || VT_UI1 != pVal.vt )
00237 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: problem accessing WMI SmbiosMajorVersion.") );
00238
00239 if(majorVersion)
00240 *majorVersion = V_UI1(&pVal);
00241
00242 VariantClear( &pVal );
00243 propName = SysAllocString( L"SmbiosMinorVersion" );
00244 hr = pSmbios->Get( propName, 0L, &pVal, &type, NULL );
00245 SysFreeString( propName );
00246
00247 if ( !SUCCEEDED( hr ) || pVal.vt != VT_UI1 )
00248 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: problem accessing WMI SmbiosMinorVersion.") );
00249
00250 if(minorVersion)
00251 *minorVersion = V_UI1(&pVal);
00252 }
00253
00254 static void GetWMISMBIOSData( WMISMBIOSINFO &smbiosData )
00255 {
00256 IWbemClassObject *pSmbios = NULL;
00257
00258 try
00259 {
00260 if (! SUCCEEDED( CoInitialize(0) ) )
00261 throw InternalErrorImpl( _("Could not initialize COM.") );
00262
00263 GetWMISMBIOSEntry( &pSmbios );
00264 GetWMISMBIOSTable( pSmbios, smbiosData );
00265 GetWMISMBIOSVersion( pSmbios, &smbiosData.majorVersion, &smbiosData.minorVersion );
00266 }
00267 catch(const exception &)
00268 {
00269 delete [] smbiosData.buffer;
00270 smbiosData.buffer = 0;
00271 throw;
00272 }
00273 CoUninitialize();
00274 }
00275
00276
00277 bool SmbiosWinWMIStrategy::getSmbiosTable(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point *table_header, bool )
00278 {
00279
00280 WMISMBIOSINFO wmi_smbiosData;
00281 memset(&wmi_smbiosData, 0, sizeof(wmi_smbiosData));
00282
00283 GetWMISMBIOSData( wmi_smbiosData );
00284
00285 if( wmi_smbiosData.bufferSize <= 0 || ! wmi_smbiosData.buffer )
00286 throw ParseExceptionImpl( _("getSmbiosTable(): GetWMISMBIOSData returned 0 for buffer size.") );
00287
00288
00289 table_header->table_length = static_cast<u16>(wmi_smbiosData.bufferSize);
00290 table_header->major_ver = wmi_smbiosData.majorVersion;
00291 table_header->minor_ver = wmi_smbiosData.minorVersion;
00292 table_header->table_num_structs = 9999;
00293
00294
00295 if( *smbiosBuffer )
00296 {
00297 memset (const_cast<u8 *>(*smbiosBuffer), 0, sizeof (**smbiosBuffer));
00298 delete [] const_cast<u8 *>(*smbiosBuffer);
00299 *smbiosBuffer = 0;
00300 }
00301
00302 *smbiosBuffer = (const u8 *) wmi_smbiosData.buffer;
00303 return true;
00304 }
00305 #else
00306 bool SmbiosWinWMIStrategy::getSmbiosTable(const u8 **, smbiosLowlevel::smbios_table_entry_point *, bool )
00307 {
00308 return false;
00309 }
00310 #endif
00311 }
00312