//*************************************************************************** // // save.cpp // // Module: WMI Instance provider code for boot parameters // // Purpose: Saving boot parameters. // // Copyright (c) 1997-1999 Microsoft Corporation // //*************************************************************************** #include "bootini.h" VOID WriteStringToFile(HANDLE fh, PCHAR str ) { DWORD dwlen; BOOL ret = WriteFile(fh, str, strlen(str), &dwlen, NULL ); } ULONG WriteDefaultParams(IWbemClassObject *pInst, PCHAR data, PCHAR def, SAFEARRAY *psa, HANDLE BootFile, PWCHAR wredir ) { VARIANT v,v1; CIMTYPE type; IWbemClassObject *pOSInst; int wlen, slen; int len; PCHAR str; BOOL found; HRESULT hret = pInst->Get(L"Default", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ return -1; } if(v.vt != VT_BSTR){ return -1; } LONG uBound; hret = SafeArrayGetUBound(psa, 1, &uBound ); for(LONG i = 0; i<=uBound; i++){ hret = SafeArrayGetElement(psa, &i, &pOSInst ); if(hret != S_OK){ pOSInst->Release(); return -1; } hret = pOSInst->Get(L"OperatingSystem", 0, &v1, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ pOSInst->Release(); return -1; } if(v1.vt != VT_BSTR){ pOSInst->Release(); return -1; } if(wcscmp(v.bstrVal,v1.bstrVal) == 0){ break; } pOSInst->Release(); } VariantClear(&v); VariantClear(&v1); PCHAR temp; if(i <= uBound){ hret = pOSInst->Get(L"Directory", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ pOSInst->Release(); return -1; } if(v.vt != VT_BSTR){ pOSInst->Release(); return -1; } wlen = wcslen(v.bstrVal); slen = wlen*sizeof(WCHAR) + 1; str = (PCHAR) BPAlloc(slen); if (!str) { return -1; } len = WideCharToMultiByte(CP_ACP, 0, v.bstrVal, wlen, str, slen-1, NULL, NULL ); str[len] = (CHAR)0; // check to see if this is a valid directory temp = strstr(data,"[operating system]"); found = FALSE; if(temp){ do{ // Remove all white spaces while(*temp == ' ' || *temp == '\r' || *temp == '\n'){ temp ++; } // check if(strncmp(str,temp,strlen(str)) == 0){ found = TRUE; WriteStringToFile(BootFile, "default=" ); WriteStringToFile(BootFile, str ); WriteStringToFile(BootFile, "\r\n" ); break; } // Go to next line while(*temp && (*temp != '\r' || *temp != '\n')){ temp ++; } }while (*temp && *temp != '['); } BPFree(str); VariantClear(&v); pOSInst->Release(); } if((found == FALSE) && def){ WriteStringToFile(BootFile, def ); WriteStringToFile(BootFile, "\r\n" ); } if(wcscmp(wredir,L"no")){ wlen = wcslen(wredir); slen = wlen*sizeof(WCHAR) + 2; str = (PCHAR) BPAlloc(slen); if (!str) { return -1; } len = WideCharToMultiByte(CP_ACP, 0, wredir, wlen, str, slen, NULL, NULL ); str[len] = (CHAR)0; WriteStringToFile(BootFile, "redirect=" ); WriteStringToFile(BootFile, str ); WriteStringToFile(BootFile, "\r\n" ); BPFree(str); } hret = pInst->Get(L"Delay", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ return -1; } if(v.vt != VT_I4){ return -1; } str = (PCHAR) BPAlloc(32); sprintf(str, "%d",v.lVal); WriteStringToFile(BootFile, "timeout=" ); WriteStringToFile(BootFile, str ); WriteStringToFile(BootFile, "\r\n" ); BPFree(str); return 0; } LONG WriteOSLine(HANDLE fh, PCHAR line, PCHAR pchar, SAFEARRAY *psa, SAFEARRAY *org, IWbemClassObject *pClass, BOOL redir ) { // Search through the entire instance for the // necessary line VARIANT v; IWbemClassObject *pOSInst; HRESULT hret; CIMTYPE type; int slen,wlen; PCHAR str; BOOL found = FALSE; SAFEARRAYBOUND sb; // Code is rendered really inefficient because of error checking // maybe should use the exception mechanism to take care of all // these errors. PWCHAR wdata = (PWCHAR)BPAlloc((pchar - line + 1)*sizeof(WCHAR) ); if(!wdata){ return -1; } int len = MultiByteToWideChar(CP_ACP, 0, line, pchar-line, wdata, pchar-line ); wdata[len] = (WCHAR)0; LONG uBound; hret = SafeArrayGetUBound(org, 1, &uBound ); if (hret != S_OK) { WriteStringToFile(fh, line ); WriteStringToFile(fh, "\r\n" ); BPFree(wdata); return 0; } for(LONG i = 0;i <= uBound; i++){ hret = SafeArrayGetElement(org, &i, &pOSInst ); if(hret != S_OK){ BPFree(wdata); return -1; } hret = pOSInst->Get(L"Directory", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BSTR){ BPFree(wdata); pOSInst->Release(); return -1; } if(wcscmp(v.bstrVal,wdata)){ pOSInst->Release(); VariantClear(&v); continue; } found = TRUE; pOSInst->Release(); VariantClear(&v); break; } if(!found){ WriteStringToFile(fh, line ); WriteStringToFile(fh, "\r\n" ); BPFree(wdata); return 0; } hret = SafeArrayGetUBound(psa, 1, &uBound ); if (hret != S_OK) { WriteStringToFile(fh, line ); WriteStringToFile(fh, "\r\n" ); return 0; } for(LONG i = 0;i <= uBound; i++){ hret = SafeArrayGetElement(psa, &i, &pOSInst ); if(hret != S_OK){ BPFree(wdata); return -1; } hret = pOSInst->Get(L"Directory", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BSTR){ BPFree(wdata); pOSInst->Release(); return -1; } if(wcscmp(v.bstrVal,wdata)){ pOSInst->Release(); VariantClear(&v); continue; } VariantClear(&v); // form the correct string. hret = pOSInst->Get(L"OperatingSystem", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BSTR){ BPFree(wdata); pOSInst->Release(); return -1; } wlen = wcslen(v.bstrVal); slen = wlen*sizeof(WCHAR) + 1; str = (PCHAR) BPAlloc(slen); if (!str) { BPFree(wdata); pOSInst->Release(); return -1; } len = WideCharToMultiByte(CP_ACP, 0, v.bstrVal, wlen, str, slen, NULL, NULL ); *pchar=0; WriteStringToFile(fh, line ); *pchar = '='; WriteStringToFile(fh, "=" ); WriteStringToFile(fh, str ); BPFree(str); VariantClear(&v); hret = pOSInst->Get(L"Rest", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BSTR){ BPFree(wdata); pOSInst->Release(); return -1; } wlen = wcslen(v.bstrVal); slen = wlen*sizeof(WCHAR) + 1; str = (PCHAR) BPAlloc(slen); if (!str) { BPFree(wdata); pOSInst->Release(); return -1; } len = WideCharToMultiByte(CP_ACP, 0, v.bstrVal, wlen, str, slen, NULL, NULL ); WriteStringToFile(fh, " " ); WriteStringToFile(fh, str ); BPFree(str); hret = pOSInst->Get(L"Redirect", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BOOL){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.boolVal && redir){// Loader also must be redirected WriteStringToFile(fh, " /redirect" ); } VariantClear(&v); hret = pOSInst->Get(L"Fastdetect", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BOOL){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.boolVal){ WriteStringToFile(fh, " /fastdetect" ); } VariantClear(&v); hret = pOSInst->Get(L"Debug", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.vt != VT_BOOL){ BPFree(wdata); pOSInst->Release(); return -1; } if(v.boolVal){ WriteStringToFile(fh, " /debug" ); } VariantClear(&v); WriteStringToFile(fh, "\r\n" ); pOSInst->Release(); found = TRUE; if(i != uBound){ // Shorten the array. After all u have a copy hret = SafeArrayGetElement(psa, &uBound, &pOSInst ); if(hret != S_OK){ BPFree(wdata); return -1; } hret = SafeArrayPutElement(psa, &i, pOSInst ); pOSInst->Release(); } sb.cElements = uBound; sb.lLbound = 0; hret = SafeArrayRedim(psa, &sb ); uBound -= 1; i-=1; // so that the currently swapped element is looked at now. } if(!found){ WriteStringToFile(fh, line ); WriteStringToFile(fh, "\r\n" ); } BPFree(wdata); return 0; } LONG SaveBootFile(IWbemClassObject *pInst, IWbemClassObject *pClass ) { VARIANT v; VARIANT v1; BOOL redir; BOOL ret; DWORD dwlen; CIMTYPE type; HRESULT hret; PCHAR temp1,pchar; SAFEARRAY *org; temp1 = NULL; PCHAR fileName = GetBootFileName(); HANDLE BootFile = GetFileHandle(fileName,OPEN_EXISTING, GENERIC_READ); BPFree(fileName); if (BootFile == INVALID_HANDLE_VALUE){ return -1; } DWORD dwsize = GetFileSize(BootFile, NULL ); if(dwsize == -1){ CloseHandle(BootFile); return -1; } PCHAR data =(PCHAR) BPAlloc(dwsize + sizeof(CHAR)); if(!data){ return -1; } DWORD dwret = ReadFile(BootFile, (LPVOID) data, dwsize, &dwlen, NULL ); if(dwret == 0){ dwret = GetLastError(); BPFree(data); CloseHandle(BootFile); return -1; } CloseHandle(BootFile); BootFile = GetFileHandle("boot.bak", TRUNCATE_EXISTING, GENERIC_WRITE); hret = pInst->Get(L"operating_systems", 0, &v, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(data); CloseHandle(BootFile); return -1; } VARTYPE t = VT_ARRAY|VT_UNKNOWN; if(v.vt != t){ BPFree(data); CloseHandle(BootFile); return -1; } hret = SafeArrayCopy(v.parray, &org); if(hret != WBEM_S_NO_ERROR){ BPFree(data); CloseHandle(BootFile); return -1; } hret = pInst->Get(L"Redirect", 0, &v1, &type, NULL ); if(hret != WBEM_S_NO_ERROR){ BPFree(data); CloseHandle(BootFile); return -1; } if(v1.vt != VT_BSTR){ BPFree(data); CloseHandle(BootFile); return -1; } redir = FALSE; if(wcscmp(v1.bstrVal,L"no")){ redir = TRUE; } CHAR sep[] = "\r\n"; PCHAR temp = strtok(data, sep); while(temp){ // ignore leading spaces while(*temp && (*temp == ' ')){ temp ++; } if (strncmp(temp,"[boot loader]",strlen("[boot loader]"))==0) { // Ok, boot loader section. Write it. do{ pchar = strchr(temp,'='); if((!pchar) ||(strncmp(temp,"default",strlen("default")) && strncmp(temp,"redirect",strlen("redirect")) && strncmp(temp,"timeout",strlen("timeout")))){ // Write the default string WriteStringToFile(BootFile,temp); WriteStringToFile(BootFile,"\r\n"); } if(strncmp(temp,"default",strlen("default")) == 0){ // store the default string temp1 = temp; } temp = strtok(NULL, sep); }while(temp && (*temp != '[')); if(WriteDefaultParams(pInst,data,temp1,v.parray,BootFile,v1.bstrVal)){ BPFree(data); CloseHandle(BootFile); return -1; } continue; } if(strcmp(temp,"[operating systems]")==0){ // dealing with the operating systems line // So get the Safe Array do{ temp1 = temp; if(*temp1 != ';'){ // comment line are ignored. pchar = strchr(temp,'='); if(pchar){ if(WriteOSLine(BootFile,temp1, pchar, org ,v.parray, pClass,redir)){ BPFree(data); CloseHandle(BootFile); return -1; } temp = strtok(NULL,sep); continue; } } WriteStringToFile(BootFile, temp); WriteStringToFile(BootFile,"\r\n"); temp = strtok(NULL,sep); }while(temp && (*temp != '[')); SafeArrayDestroy(org); VariantClear(&v); continue; } WriteStringToFile(BootFile,temp); WriteStringToFile(BootFile,"\r\n"); temp = strtok(NULL,sep); } CloseHandle(BootFile); fileName = GetBootFileName(); if(!fileName){ return -1; } ret = CopyFile("boot.bak", fileName, FALSE ); BPFree(fileName); return 0; }