Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

SmbiosStrategy_Windows.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
00003  *
00004  * Copyright (C) 2005 Dell Inc.
00005  *  by Michael Brown <Michael_E_Brown@dell.com>
00006  * Licensed under the Open Software License version 2.1
00007  *
00008  * Alternatively, you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published
00010  * by the Free Software Foundation; either version 2 of the License,
00011  * or (at your option) any later version.
00012 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  */
00018 
00019 // compat header should always be first header if including system headers
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022 
00023 #include <iostream>
00024 #include <sstream>
00025 
00026 /* stuff for WMI. needs SDK, so is optional. */
00027 #ifdef LIBSMBIOS_WIN_USE_WMI
00028 #   ifndef _WIN32_DCOM
00029 #   define _WIN32_DCOM
00030 #   endif
00031 
00032 // this pragma statment will automatically add the 'wbemuuid.lib' library
00033 // to program library link list
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 // message.h should be included last.
00045 #include "smbios/message.h"
00046 
00047 using namespace smbiosLowlevel;
00048 using namespace std;
00049 
00050 namespace smbios
00051 {
00052     // Non Member Functions
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         // Donot return false since these APIs are only available on W2K3 SP1 and higher.
00064         // returning FALSE will break libsmbios on W2K and W2K3( no SP )
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         // new throws exception, no need to test.
00074         u8 *newSmbiosBuffer = 0;
00075 
00076         DWORD iSignature =             'R'; //RSMB
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         // populate buffer with table.
00098         // Note that this is not the actual smbios table:
00099         // From MS: The layout of the data returned by the raw SMBIOS table
00100         //          provider is identical to the data returned by the
00101         //          MSSmBIOS_RawSMBiosTables WMI class.  The
00102         //          MSSmBIOS_RawSMBiosTables class is located in the root\wmi
00103         //          namespace.
00104         GetSystemFirmwareTable( iSignature, 0, newSmbiosBuffer, iBufferSizeNeeded );
00105 
00106         // Have to manually set values in header because we cannot get table entry point using this api
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         // get rid of header that MS tacks on.
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         //delete old one, if necessary
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     /* NON-MEMBER functions to help parse WMI data. */
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             /* No need to throw exception on failure for CoInitializeSecurity() because other user may have already
00150                initialized it properly.
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         // new throws exception, no need to test.
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         // fake version information for now.
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         //delete old one, if necessary
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 /* LIBSMBIOS_WIN_USE_WMI */
00311 }
00312 

Generated on Wed Apr 11 16:25:10 2007 for SMBIOS Library by doxygen 1.3.5