windows-nt/Source/XPSP1/NT/base/headless/bootprov/getparams.cpp
2020-09-26 16:20:57 +08:00

535 lines
16 KiB
C++

//***************************************************************************
//
// getparams.cpp
//
// Module: WMI Instance provider code for boot parameters
//
// Purpose: Extracting boot parameters.
//
// Copyright (c) 1997-1999 Microsoft Corporation
//
//***************************************************************************
#include "bootini.h"
SCODE ParseLine(IWbemClassObject *pNewOSInst,
PCHAR line,
PCHAR options
)
{
PCHAR rest; // the rest of the options cannot be bigger than this.
int size = strlen(line);
int len;
SCODE sc;
VARIANT v;
BOOL found=FALSE;
rest = (PCHAR) BPAlloc(size);
if (!rest) {
return WBEM_E_FAILED;
}
PWCHAR wstr;
wstr = (PWCHAR) BPAlloc(size*sizeof(WCHAR));
if (!wstr) {
BPFree(rest);
return WBEM_E_FAILED;
}
*options = 0; //Later fill in the '='
len = MultiByteToWideChar(CP_ACP,
0,
line,
strlen(line),
wstr,
size
);
wstr[len] = (WCHAR) 0;
v.vt = VT_BSTR;
v.bstrVal = SysAllocString(wstr);
sc = pNewOSInst->Put(L"Directory", 0,&v, 0);
VariantClear(&v);
PCHAR temp = options + 1;
*options = '=';
PCHAR temp1;
// Rest of the stuff is filled in during initialization
while(*temp){ // We know line ends with a null
while(*temp && *temp == ' '){
temp ++;
}
if(*temp == 0) break;
// Get the new string
temp1 = temp;
if(*temp == '"'){
// could be the name of the OS
do {
temp1++;
}while(*temp1 && (*temp1 != '"'));
if(*temp1){
temp1++;
}
else{
BPFree(rest);
BPFree(wstr);
return WBEM_E_FAILED;
}
len = MultiByteToWideChar(CP_ACP,
0,
temp,
temp1-temp,
wstr,
size
);
wstr[len] = (WCHAR) 0;
v.vt = VT_BSTR;
v.bstrVal = SysAllocString(wstr);
sc = pNewOSInst->Put(L"OperatingSystem", 0,&v, 0);
VariantClear(&v);
temp = temp1;
continue;
}
do{
temp1++;
}while((*temp1) && (*temp1 != ' ') && (*temp1 != '/'));
// Now we have the option between temp1 and temp2.
if(strncmp(temp,"/redirect", strlen("/redirect")) == 0){
v.vt = VT_BOOL;
v.boolVal = TRUE;
sc = pNewOSInst->Put(L"Redirect", 0,&v, 0);
VariantClear(&v);
temp = temp1;
continue;
}
if(strncmp(temp,"/debug", strlen("/debug")) == 0){
// fill in the redirect flag.
v.vt = VT_BOOL;
v.boolVal = TRUE;
sc = pNewOSInst->Put(L"Debug", 0,&v, 0);
VariantClear(&v);
temp = temp1;
continue;
}
if(strncmp(temp,"/fastdetect", strlen("/fastdetect")) == 0){
// fill in the redirect flag.
v.vt = VT_BOOL;
v.boolVal = TRUE;
sc = pNewOSInst->Put(L"Fastdetect", 0,&v, 0);
VariantClear(&v);
temp = temp1;
continue;
}
strncat(rest,temp, temp1-temp);
strcat(rest," ");
temp = temp1;
}
len = MultiByteToWideChar(CP_ACP,
0,
rest,
strlen(rest),
wstr,
size
);
wstr[len] = (WCHAR) 0;
v.vt=VT_BSTR;
v.bstrVal = SysAllocString(wstr);
sc = pNewOSInst->Put(L"Rest", 0,&v, 0);
VariantClear(&v);
BPFree(rest);
BPFree(wstr);
return sc;
}
SCODE
ParseBootFile(IWbemClassObject *pClass,
PCHAR data,
PWCHAR *wdef,
PCHAR red,
PLONG pdelay,
SAFEARRAY **psa
)
{
IWbemClassObject FAR* pNewOSInst;
HRESULT ret;
int dwRet;
SCODE sc;
SAFEARRAYBOUND bound[1];
long index;
PCHAR def=NULL;
PCHAR pChar;
VARIANT v;
HRESULT hret;
CIMTYPE type;
// Ok, start string manipulation.
// Read each line and glean the required information
CHAR sep[] = "\r\n";
PCHAR temp1;
PCHAR temp = strtok(data,sep);
int i = 0;
strcpy(red,"no"); // Put in the default values for these.
*pdelay = 30;
while(temp){
// Ignore spaces
while(*temp && *temp == ' '){
temp++;
}
if(*temp == ';'){// comment line
temp = strtok(NULL,sep);
continue;
}
if(strncmp(temp,"[boot loader]",strlen("[boot loader]"))==0){
do{
temp1 = strchr(temp,'=');
if(!temp1){
// weird stuff is going on
// could be a comment line or some such thing
temp = strtok(NULL,sep);
continue;
}
else{
temp1++;
}
while(*temp1 && *temp1 == ' ' ){
temp1++;
}
if(strncmp(temp,"default",strlen("default"))==0){
def= temp1;
temp = strtok(NULL,sep);
continue;
}
if(strncmp(temp,"redirect",strlen("redirect"))==0){
sscanf(temp1, "%s",red);
temp = strtok(NULL,sep);
continue;
}
if(strncmp(temp,"timeout=",strlen("timeout="))==0){
sscanf(temp1, "%d",pdelay);
}
temp = strtok(NULL,sep);
}while(temp && (*temp != '[')); // next section has begun
continue;
}
if(strncmp(temp,"[operating systems]",strlen("[operating systems]")) == 0){
bound[0].lLbound = 0;
bound[0].cElements = 0;
*psa = SafeArrayCreate(VT_UNKNOWN,
1,
bound
);
if(*psa == NULL){
return WBEM_E_FAILED;
}
do{
// Trim leading spaces
while (*temp == ' '){
temp ++;
}
// Skip comment lines
if ( *temp != ';' ){
// pChar will point at the directory
PCHAR pChar = strchr(temp,'=');
// We must have an = sign or this is an invalid string
if (pChar){
// Punch in a null
// Increase the number of elements
index = (long) bound[0].cElements;
bound[0].cElements += 1;
ret = SafeArrayRedim(*psa,
bound
);
if(ret != S_OK){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
sc = pClass->SpawnInstance(0,&pNewOSInst);
// Start filling in the new instance
if(FAILED(sc)){
SafeArrayDestroy(*psa);
return sc;
}
sc = ParseLine(pNewOSInst,temp,pChar);
if (sc != S_OK) {
SafeArrayDestroy(*psa);
return sc;
}
ret = SafeArrayPutElement(*psa,
&index,
pNewOSInst
);
if(ret != S_OK){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
}
}
temp = strtok(NULL,sep);
}while(temp && (*temp != '['));
}
}
// Now find out if the default operating system is in one of the
// Convert the default string to a proper displayable value.
if(def){
int size = strlen(def);
int len;
*wdef = (PWCHAR) BPAlloc((size+1)*sizeof(WCHAR));
if(*wdef == NULL){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
len = MultiByteToWideChar(CP_ACP,
0,
def,
size,
*wdef,
size
);
(*wdef)[len] = (WCHAR) 0;
LONG uBound;
IWbemClassObject *pOSInst;
hret = SafeArrayGetUBound(*psa,
1,
&uBound
);
LONG i;
for(i = 0; i<=uBound; i++){
hret = SafeArrayGetElement(*psa,
&i,
&pOSInst
);
if(hret != S_OK){
pOSInst->Release();
SafeArrayDestroy(*psa);
BPFree(*wdef);
return WBEM_E_FAILED;
}
hret = pOSInst->Get(L"Directory",
0,
&v,
&type,
NULL
);
if(hret != WBEM_S_NO_ERROR){
SafeArrayDestroy(*psa);
pOSInst->Release();
BPFree(*wdef);
return -1;
}
if(v.vt != VT_BSTR){
SafeArrayDestroy(*psa);
pOSInst->Release();
BPFree(*wdef);
return -1;
}
if(wcscmp(v.bstrVal,*wdef) == 0){
VariantClear(&v);
break;
}
}
BPFree(*wdef);
if(i > uBound){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
hret=pOSInst->Get(L"OperatingSystem",
0,
&v,
&type,
NULL
);
pOSInst->Release();
if(hret != WBEM_S_NO_ERROR){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
if(v.vt != VT_BSTR){
SafeArrayDestroy(*psa);
return WBEM_E_FAILED;
}
*wdef = (PWCHAR) BPAlloc(wcslen(v.bstrVal) + sizeof(WCHAR));
if(*wdef == NULL){
return -1;
}
wcscpy(*wdef,v.bstrVal);
VariantClear(&v);
}
return S_OK;
}
SCODE
GetLoaderParameters(HANDLE BootFile,
IWbemClassObject *pNewInst,
IWbemClassObject *pClass
)
{
// Read the entire file into memory if you can otherwise forget about it.
VARIANT v;
LONG dwret;
SCODE sc;
DWORD dwlen;
DWORD dwsize = GetFileSize(BootFile,
NULL
);
if(dwsize == -1){
return WBEM_E_FAILED;
}
PCHAR data =(PCHAR) BPAlloc(dwsize + sizeof(CHAR));
if(!data){
return WBEM_E_FAILED;
}
dwret = ReadFile(BootFile,
(LPVOID) data,
dwsize,
&dwlen,
NULL
);
if(dwret == 0){
BPFree(data);
return GetLastError();
}
// Parse the code and return the answers in two arrays, and a safe array
SAFEARRAY *psa;
CHAR red[32];
LONG delay;
PWCHAR wdef=NULL;
sc = ParseBootFile(pClass,
data,
&wdef,
red,
&delay,
&psa
);
BPFree(data);
if (sc != S_OK) {
return sc;
}
// fill in the New Instance
// Fill in the default OS.
v.vt = VT_BSTR;
int len;
v.bstrVal = SysAllocString(wdef);
sc = pNewInst->Put(L"Default", 0,&v, 0);
VariantClear(&v);
BPFree(wdef);
//Fill in the redirect parameter
WCHAR wred[32];
len = MultiByteToWideChar(CP_ACP,
0,
red,
strlen(red),
wred,
32
);
wred[len] = (WCHAR) 0;
v.vt = VT_BSTR;
v.bstrVal = SysAllocString(wred);
sc = pNewInst->Put(L"Redirect", 0, &v, 0);
VariantClear(&v);
// Fill in the delay
v.vt = VT_I4;
v.lVal = delay;
sc = pNewInst->Put(L"Delay", 0, &v, 0);
VariantClear(&v);
// Fill in the OS in the file
v.vt = VT_ARRAY|VT_UNKNOWN;
v.parray = psa;
sc = pNewInst->Put(L"operating_systems", 0, &v, 0);
VariantClear(&v);
return S_OK;
}
//BOOLEAN first=TRUE;
SCODE
GetBootLoaderParameters(IWbemServices * m_pNamespace,
IWbemClassObject *pNewInst,
IWbemContext *pCtx
)
{
HANDLE BootFile;
SCODE sc;
IWbemClassObject *pClass;
IWbemObjectTextSrc *pSrc;
BSTR strText;
HRESULT hr;
/*
if (first) {
first = FALSE;
return WBEM_E_FAILED;
}
*/
// Read the file and set in the values.
if(pNewInst == NULL){
return WBEM_E_INVALID_PARAMETER;
}
// Get a handle to the boot file.
PCHAR data = GetBootFileName();
if(!data){
return WBEM_E_FAILED;
}
BootFile = GetFileHandle(data,OPEN_EXISTING,GENERIC_READ);
BPFree(data);
if(BootFile == INVALID_HANDLE_VALUE){
return WBEM_E_FAILED;
}
sc = m_pNamespace->GetObject(L"OSParameters", 0, pCtx, &pClass, NULL);
if (sc != S_OK) {
return WBEM_E_FAILED;
}
sc = GetLoaderParameters(BootFile, pNewInst, pClass);
CloseHandle(BootFile);
pClass->Release();
if (sc != S_OK) {
return WBEM_E_FAILED;
}
pSrc = NULL;
IWbemClassObject *pInstance;
if(SUCCEEDED(hr = CoCreateInstance (CLSID_WbemObjectTextSrc, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemObjectTextSrc, (void**) &pSrc))) {
if (pSrc) {
if(SUCCEEDED(hr = pSrc->GetText(0, pNewInst, WMI_OBJ_TEXT_WMI_DTD_2_0, pCtx, &strText))) {
if( SUCCEEDED( hr = pSrc->CreateFromText( 0, strText, WMI_OBJ_TEXT_WMI_DTD_2_0,
NULL, &pInstance) ) ) {
pInstance->Release();
sc = 0;
} else {
sc = hr;
}
SysFreeString(strText);
}
else {
printf("GetText failed with %x\n", hr);
}
pSrc->Release();
}
}
else
printf("CoCreateInstance on WbemObjectTextSrc failed with %x\n", hr);
return sc;
}