Update dependencies
This commit is contained in:
155
vendor/github.com/digitalocean/go-smbios/smbios/stream_windows.go
generated
vendored
Normal file
155
vendor/github.com/digitalocean/go-smbios/smbios/stream_windows.go
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2017-2018 DigitalOcean.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package smbios
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// firmwareTableProviderSigRSMB is the identifier for the raw SMBIOS firmware table
|
||||
// provider.
|
||||
// It is equal to the ASCII characters 'RSMB' packed into a uint32.
|
||||
// In the C++ example code in the MSDN documentation, this is specified using
|
||||
// multi-byte character literals, which are automatically coerced to an integer by
|
||||
// the C++ compiler.
|
||||
const firmwareTableProviderSigRSMB uint32 = 0x52534d42
|
||||
|
||||
// smbiosDataHeaderSize is size of the "header" (non-variable) part of the
|
||||
// RawSMBIOSData struct. This serves as both the offset to the actual
|
||||
// SMBIOS table data, and the minimum possible size of a valid RawSMBIOSDATA
|
||||
// struct (with a table length of 0).
|
||||
const rawSMBIOSDataHeaderSize = 8
|
||||
|
||||
var (
|
||||
libKernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
// MSDN Documentation for GetSystemFirmwareTable:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724379(v=vs.85).aspx
|
||||
procGetSystemFirmwareTable = libKernel32.NewProc("GetSystemFirmwareTable")
|
||||
)
|
||||
|
||||
// nativeEndian returns the native byte order of this system.
|
||||
func nativeEndian() binary.ByteOrder {
|
||||
// Determine endianness by interpreting a uint16 as a byte slice.
|
||||
v := uint16(1)
|
||||
b := *(*[2]byte)(unsafe.Pointer(&v))
|
||||
|
||||
if b[0] == 1 {
|
||||
return binary.LittleEndian
|
||||
}
|
||||
|
||||
return binary.BigEndian
|
||||
}
|
||||
|
||||
// windowsStream parses the data returned from GetSystemFirmwareTable('RSMB',...)
|
||||
// and returns a stream and entrypoint that can be used to decode the system's
|
||||
// SMBIOS table.
|
||||
//
|
||||
// When calling GetSystemFirmwareTable with FirmwareTableProviderSignature = "RSMB",
|
||||
// Windows will write a RawSMBIOSData struct into the output buffer.
|
||||
// Thus, `buf` is expected to contain a valid RawSMBIOSData structure.
|
||||
//
|
||||
// From windows.h:
|
||||
//
|
||||
// struct RawSMBIOSData {
|
||||
// BYTE Used20CallingMethod;
|
||||
// BYTE SMBIOSMajorVersion;
|
||||
// BYTE SMBIOSMinorVersion;
|
||||
// BYTE DMIRevision;
|
||||
// DWORD Length;
|
||||
// BYTE SMBIOSTableData[];
|
||||
// }
|
||||
//
|
||||
// Note: a DWORD is equivalent to a uint32
|
||||
// See: https://msdn.microsoft.com/en-us/library/cc230318.aspx
|
||||
func windowsStream(buf []byte) (io.ReadCloser, EntryPoint, error) {
|
||||
bufLen := uint32(len(buf))
|
||||
|
||||
// Do an additional check to make sure the actual amount written is sane.
|
||||
if bufLen < rawSMBIOSDataHeaderSize {
|
||||
return nil, nil, fmt.Errorf("GetSystemFirmwareTable wrote less data than expected: wrote %d bytes, expected at least 8 bytes", bufLen)
|
||||
}
|
||||
|
||||
tableSize := nativeEndian().Uint32(buf[4:8])
|
||||
if rawSMBIOSDataHeaderSize+tableSize > bufLen {
|
||||
return nil, nil, errors.New("reported SMBIOS table size exceeds buffer")
|
||||
}
|
||||
|
||||
entryPoint := &WindowsEntryPoint{
|
||||
MajorVersion: buf[1],
|
||||
MinorVersion: buf[2],
|
||||
Revision: buf[3],
|
||||
Size: tableSize,
|
||||
}
|
||||
|
||||
tableBuff := buf[rawSMBIOSDataHeaderSize : rawSMBIOSDataHeaderSize+tableSize]
|
||||
|
||||
return ioutil.NopCloser(bytes.NewReader(tableBuff)), entryPoint, nil
|
||||
}
|
||||
|
||||
func stream() (io.ReadCloser, EntryPoint, error) {
|
||||
// Call first with empty buffer to get size.
|
||||
r1, _, err := procGetSystemFirmwareTable.Call(
|
||||
uintptr(firmwareTableProviderSigRSMB), // FirmwareTableProviderSignature = 'RSMB'
|
||||
0, // FirmwareTableID = 0
|
||||
0, // pFirmwareTableBuffer = NULL
|
||||
0, // BufferSize = 0
|
||||
)
|
||||
|
||||
// LazyProc.Call will always return err != nil, so we need to check the primary
|
||||
// return value (r1) to determine whether or not an error occurred.
|
||||
// In this case, r1 should contain the size of the needed buffer, so it will only
|
||||
// be 0 if the function call failed for some reason.
|
||||
//
|
||||
// Godoc for LazyProc.Call:
|
||||
// https://golang.org/pkg/syscall/?GOOS=windows&GOARCH=amd64#LazyProc.Call
|
||||
if r1 == 0 {
|
||||
return nil, nil, fmt.Errorf("failed to determine size of buffer needed: %v", err)
|
||||
}
|
||||
if r1 < rawSMBIOSDataHeaderSize {
|
||||
return nil, nil, fmt.Errorf("reported buffer size smaller than expected: reported %d, expected >= 8", r1)
|
||||
}
|
||||
|
||||
bufferSize := uint32(r1)
|
||||
buffer := make([]byte, bufferSize)
|
||||
|
||||
r1, _, err = procGetSystemFirmwareTable.Call(
|
||||
uintptr(firmwareTableProviderSigRSMB), // FirmwareTableProviderSignature = 'RSMB'
|
||||
0, // FirmwareTableID = 0
|
||||
uintptr(unsafe.Pointer(&buffer[0])), // pFirmwareTableBuffer = &buffer
|
||||
uintptr(bufferSize), // BufferSize = bufferSize
|
||||
)
|
||||
bytesWritten := uint32(r1)
|
||||
|
||||
// Check for the two possible failure cases documented in API:
|
||||
if bytesWritten > bufferSize {
|
||||
return nil, nil, fmt.Errorf("buffer size was too small, somehow: have %d bytes, Windows wanted %d bytes", bufferSize, bytesWritten)
|
||||
}
|
||||
if bytesWritten == 0 {
|
||||
return nil, nil, fmt.Errorf("failed to read SMBIOS data: %v", err)
|
||||
}
|
||||
|
||||
// At this point, bytesWritten <= bufferSize, which means the call succeeded as
|
||||
// per the MSDN documentation.
|
||||
|
||||
return windowsStream(buffer[:bytesWritten])
|
||||
}
|
||||
Reference in New Issue
Block a user