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( "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 if (! SUCCEEDED( hr ) )
00150 throw InternalErrorImpl(_("CoInitializeSecurity() failed"));
00151
00152 hr = CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLocator );
00153
00154 if (! SUCCEEDED( hr ) )
00155 throw InternalErrorImpl(_("CoCreateInstance() failed for locator"));
00156
00157 hr = pLocator->ConnectServer(path, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace );
00158 pLocator->Release();
00159
00160 if( WBEM_S_NO_ERROR != hr )
00161 throw InternalErrorImpl(_("ConnectServer() failed for namespace"));
00162
00163 hr = pNamespace->CreateInstanceEnum( className, 0, NULL, &pEnumSMBIOS );
00164 pNamespace->Release();
00165
00166 if (! SUCCEEDED( hr ) )
00167 throw InternalErrorImpl(_("CreateInstanceEnum() failed for MSSmBios_RawSMBiosTables"));
00168
00169 hr = pEnumSMBIOS->Next( 4000, 1, pSmbios, &uReturned );
00170 pEnumSMBIOS->Release();
00171
00172 if ( 1 != uReturned )
00173 throw InternalErrorImpl(_("Next() failed for pEnumSMBIOS"));
00174 }
00175 catch(const exception &)
00176 {
00177 SysFreeString(className);
00178 SysFreeString(path);
00179 throw;
00180 }
00181 }
00182
00183
00184 static void GetWMISMBIOSTable( IWbemClassObject *pSmbios, WMISMBIOSINFO &smbiosData )
00185 {
00186 BSTR propName;
00187 CIMTYPE type;
00188 VARIANT pVal;
00189 SAFEARRAY *parray = NULL;
00190
00191 if ( NULL == pSmbios )
00192 throw ParseExceptionImpl( _("GetWMISMBIOSTable: NULL pointer to SMBIOS Entry specified.") );
00193
00194 VariantInit(&pVal);
00195
00196 propName = SysAllocString(L"SMBiosData");
00197 pSmbios->Get( propName, 0L, &pVal, &type, NULL);
00198 SysFreeString(propName);
00199
00200 if ( ( VT_UI1 | VT_ARRAY ) != pVal.vt )
00201 throw ParseExceptionImpl( _("GetWMISMBIOSTable: SMBiosData returned unknown entry type.") );
00202
00203 parray = V_ARRAY(&pVal);
00204
00205 smbiosData.bufferSize = parray->rgsabound[0].cElements;
00206
00207 if ( smbiosData.bufferSize == 0 )
00208 throw ParseExceptionImpl( _("GetWMISMBIOSTable: Buffer size was zero.") );
00209
00210 smbiosData.buffer = new u8[smbiosData.bufferSize];
00211 if ( ! smbiosData.buffer )
00212 throw ParseExceptionImpl( _("GetWMISMBIOSTable: Failed to allocate memory for SMBIOS table.") );
00213
00214 memcpy(smbiosData.buffer, (u8 *)parray->pvData, smbiosData.bufferSize);
00215 }
00216
00217 static void GetWMISMBIOSVersion( IWbemClassObject *pSmbios, u8 *majorVersion, u8 *minorVersion )
00218 {
00219 BSTR propName;
00220 HRESULT hr = S_OK;
00221 CIMTYPE type;
00222 VARIANT pVal;
00223
00224 if ( NULL == pSmbios )
00225 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: null pointer passed as pSmbios.") );
00226
00227 VariantInit( &pVal );
00228 propName = SysAllocString( L"SmbiosMajorVersion" );
00229 hr = pSmbios->Get( propName, 0L, &pVal, &type, NULL );
00230 SysFreeString( propName );
00231
00232 if ( ! SUCCEEDED( hr ) || VT_UI1 != pVal.vt )
00233 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: problem accessing WMI SmbiosMajorVersion.") );
00234
00235 if(majorVersion)
00236 *majorVersion = V_UI1(&pVal);
00237
00238 VariantClear( &pVal );
00239 propName = SysAllocString( L"SmbiosMinorVersion" );
00240 hr = pSmbios->Get( propName, 0L, &pVal, &type, NULL );
00241 SysFreeString( propName );
00242
00243 if ( !SUCCEEDED( hr ) || pVal.vt != VT_UI1 )
00244 throw ParseExceptionImpl( _("GetWMISMBIOSVersion: problem accessing WMI SmbiosMinorVersion.") );
00245
00246 if(minorVersion)
00247 *minorVersion = V_UI1(&pVal);
00248 }
00249
00250 static void GetWMISMBIOSData( WMISMBIOSINFO &smbiosData )
00251 {
00252 IWbemClassObject *pSmbios = NULL;
00253
00254 try
00255 {
00256 if (! SUCCEEDED( CoInitialize(0) ) )
00257 throw InternalErrorImpl( _("Could not initialize COM.") );
00258
00259 GetWMISMBIOSEntry( &pSmbios );
00260 GetWMISMBIOSTable( pSmbios, smbiosData );
00261 GetWMISMBIOSVersion( pSmbios, &smbiosData.majorVersion, &smbiosData.minorVersion );
00262 }
00263 catch(const exception &)
00264 {
00265 delete [] smbiosData.buffer;
00266 smbiosData.buffer = 0;
00267 throw;
00268 }
00269 CoUninitialize();
00270 }
00271
00272
00273 bool SmbiosWinWMIStrategy::getSmbiosTable(const u8 **smbiosBuffer, smbiosLowlevel::smbios_table_entry_point *table_header, bool )
00274 {
00275
00276 WMISMBIOSINFO wmi_smbiosData;
00277 memset(&wmi_smbiosData, 0, sizeof(wmi_smbiosData));
00278
00279 GetWMISMBIOSData( wmi_smbiosData );
00280
00281 if( wmi_smbiosData.bufferSize <= 0 || ! wmi_smbiosData.buffer )
00282 throw ParseExceptionImpl( _("getSmbiosTable(): GetWMISMBIOSData returned 0 for buffer size.") );
00283
00284
00285 table_header->table_length = static_cast<u16>(wmi_smbiosData.bufferSize);
00286 table_header->major_ver = wmi_smbiosData.majorVersion;
00287 table_header->minor_ver = wmi_smbiosData.minorVersion;
00288 table_header->table_num_structs = 9999;
00289
00290
00291 if( *smbiosBuffer )
00292 {
00293 memset (const_cast<u8 *>(*smbiosBuffer), 0, sizeof (**smbiosBuffer));
00294 delete [] const_cast<u8 *>(*smbiosBuffer);
00295 *smbiosBuffer = 0;
00296 }
00297
00298 *smbiosBuffer = (const u8 *) wmi_smbiosData.buffer;
00299 return true;
00300 }
00301 #else
00302 bool SmbiosWinWMIStrategy::getSmbiosTable(const u8 **, smbiosLowlevel::smbios_table_entry_point *, bool )
00303 {
00304 return false;
00305 }
00306 #endif
00307 }
00308