Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

733 lines
20 KiB

  1. //***************************************************************************
  2. //
  3. // save.cpp
  4. //
  5. // Module: WMI Instance provider code for boot parameters
  6. //
  7. // Purpose: Saving boot parameters.
  8. //
  9. // Copyright (c) 1997-1999 Microsoft Corporation
  10. //
  11. //***************************************************************************
  12. #include "bootini.h"
  13. VOID
  14. WriteStringToFile(HANDLE fh,
  15. PCHAR str
  16. )
  17. {
  18. DWORD dwlen;
  19. BOOL ret = WriteFile(fh,
  20. str,
  21. strlen(str),
  22. &dwlen,
  23. NULL
  24. );
  25. }
  26. ULONG
  27. WriteDefaultParams(IWbemClassObject *pInst,
  28. PCHAR data,
  29. PCHAR def,
  30. SAFEARRAY *psa,
  31. HANDLE BootFile,
  32. PWCHAR wredir
  33. )
  34. {
  35. VARIANT v,v1;
  36. CIMTYPE type;
  37. IWbemClassObject *pOSInst;
  38. int wlen, slen;
  39. int len;
  40. PCHAR str;
  41. BOOL found;
  42. HRESULT hret = pInst->Get(L"Default",
  43. 0,
  44. &v,
  45. &type,
  46. NULL
  47. );
  48. if(hret != WBEM_S_NO_ERROR){
  49. return -1;
  50. }
  51. if(v.vt != VT_BSTR){
  52. return -1;
  53. }
  54. LONG uBound;
  55. hret = SafeArrayGetUBound(psa,
  56. 1,
  57. &uBound
  58. );
  59. for(LONG i = 0; i<=uBound; i++){
  60. hret = SafeArrayGetElement(psa,
  61. &i,
  62. &pOSInst
  63. );
  64. if(hret != S_OK){
  65. pOSInst->Release();
  66. return -1;
  67. }
  68. hret = pOSInst->Get(L"OperatingSystem",
  69. 0,
  70. &v1,
  71. &type,
  72. NULL
  73. );
  74. if(hret != WBEM_S_NO_ERROR){
  75. pOSInst->Release();
  76. return -1;
  77. }
  78. if(v1.vt != VT_BSTR){
  79. pOSInst->Release();
  80. return -1;
  81. }
  82. if(wcscmp(v.bstrVal,v1.bstrVal) == 0){
  83. break;
  84. }
  85. pOSInst->Release();
  86. }
  87. VariantClear(&v);
  88. VariantClear(&v1);
  89. PCHAR temp;
  90. if(i <= uBound){
  91. hret = pOSInst->Get(L"Directory",
  92. 0,
  93. &v,
  94. &type,
  95. NULL
  96. );
  97. if(hret != WBEM_S_NO_ERROR){
  98. pOSInst->Release();
  99. return -1;
  100. }
  101. if(v.vt != VT_BSTR){
  102. pOSInst->Release();
  103. return -1;
  104. }
  105. wlen = wcslen(v.bstrVal);
  106. slen = wlen*sizeof(WCHAR) + 1;
  107. str = (PCHAR) BPAlloc(slen);
  108. if (!str) {
  109. return -1;
  110. }
  111. len = WideCharToMultiByte(CP_ACP,
  112. 0,
  113. v.bstrVal,
  114. wlen,
  115. str,
  116. slen-1,
  117. NULL,
  118. NULL
  119. );
  120. str[len] = (CHAR)0;
  121. // check to see if this is a valid directory
  122. temp = strstr(data,"[operating system]");
  123. found = FALSE;
  124. if(temp){
  125. do{
  126. // Remove all white spaces
  127. while(*temp == ' ' || *temp == '\r' || *temp == '\n'){
  128. temp ++;
  129. }
  130. // check
  131. if(strncmp(str,temp,strlen(str)) == 0){
  132. found = TRUE;
  133. WriteStringToFile(BootFile,
  134. "default="
  135. );
  136. WriteStringToFile(BootFile,
  137. str
  138. );
  139. WriteStringToFile(BootFile,
  140. "\r\n"
  141. );
  142. break;
  143. }
  144. // Go to next line
  145. while(*temp && (*temp != '\r' || *temp != '\n')){
  146. temp ++;
  147. }
  148. }while (*temp && *temp != '[');
  149. }
  150. BPFree(str);
  151. VariantClear(&v);
  152. pOSInst->Release();
  153. }
  154. if((found == FALSE) && def){
  155. WriteStringToFile(BootFile,
  156. def
  157. );
  158. WriteStringToFile(BootFile,
  159. "\r\n"
  160. );
  161. }
  162. if(wcscmp(wredir,L"no")){
  163. wlen = wcslen(wredir);
  164. slen = wlen*sizeof(WCHAR) + 2;
  165. str = (PCHAR) BPAlloc(slen);
  166. if (!str) {
  167. return -1;
  168. }
  169. len = WideCharToMultiByte(CP_ACP,
  170. 0,
  171. wredir,
  172. wlen,
  173. str,
  174. slen,
  175. NULL,
  176. NULL
  177. );
  178. str[len] = (CHAR)0;
  179. WriteStringToFile(BootFile,
  180. "redirect="
  181. );
  182. WriteStringToFile(BootFile,
  183. str
  184. );
  185. WriteStringToFile(BootFile,
  186. "\r\n"
  187. );
  188. BPFree(str);
  189. }
  190. hret = pInst->Get(L"Delay",
  191. 0,
  192. &v,
  193. &type,
  194. NULL
  195. );
  196. if(hret != WBEM_S_NO_ERROR){
  197. return -1;
  198. }
  199. if(v.vt != VT_I4){
  200. return -1;
  201. }
  202. str = (PCHAR) BPAlloc(32);
  203. sprintf(str, "%d",v.lVal);
  204. WriteStringToFile(BootFile,
  205. "timeout="
  206. );
  207. WriteStringToFile(BootFile,
  208. str
  209. );
  210. WriteStringToFile(BootFile,
  211. "\r\n"
  212. );
  213. BPFree(str);
  214. return 0;
  215. }
  216. LONG
  217. WriteOSLine(HANDLE fh,
  218. PCHAR line,
  219. PCHAR pchar,
  220. SAFEARRAY *psa,
  221. SAFEARRAY *org,
  222. IWbemClassObject *pClass,
  223. BOOL redir
  224. )
  225. {
  226. // Search through the entire instance for the
  227. // necessary line
  228. VARIANT v;
  229. IWbemClassObject *pOSInst;
  230. HRESULT hret;
  231. CIMTYPE type;
  232. int slen,wlen;
  233. PCHAR str;
  234. BOOL found = FALSE;
  235. SAFEARRAYBOUND sb;
  236. // Code is rendered really inefficient because of error checking
  237. // maybe should use the exception mechanism to take care of all
  238. // these errors.
  239. PWCHAR wdata = (PWCHAR)BPAlloc((pchar - line + 1)*sizeof(WCHAR)
  240. );
  241. if(!wdata){
  242. return -1;
  243. }
  244. int len = MultiByteToWideChar(CP_ACP,
  245. 0,
  246. line,
  247. pchar-line,
  248. wdata,
  249. pchar-line
  250. );
  251. wdata[len] = (WCHAR)0;
  252. LONG uBound;
  253. hret = SafeArrayGetUBound(org,
  254. 1,
  255. &uBound
  256. );
  257. if (hret != S_OK) {
  258. WriteStringToFile(fh,
  259. line
  260. );
  261. WriteStringToFile(fh,
  262. "\r\n"
  263. );
  264. BPFree(wdata);
  265. return 0;
  266. }
  267. for(LONG i = 0;i <= uBound; i++){
  268. hret = SafeArrayGetElement(org,
  269. &i,
  270. &pOSInst
  271. );
  272. if(hret != S_OK){
  273. BPFree(wdata);
  274. return -1;
  275. }
  276. hret = pOSInst->Get(L"Directory",
  277. 0,
  278. &v,
  279. &type,
  280. NULL
  281. );
  282. if(hret != WBEM_S_NO_ERROR){
  283. BPFree(wdata);
  284. pOSInst->Release();
  285. return -1;
  286. }
  287. if(v.vt != VT_BSTR){
  288. BPFree(wdata);
  289. pOSInst->Release();
  290. return -1;
  291. }
  292. if(wcscmp(v.bstrVal,wdata)){
  293. pOSInst->Release();
  294. VariantClear(&v);
  295. continue;
  296. }
  297. found = TRUE;
  298. pOSInst->Release();
  299. VariantClear(&v);
  300. break;
  301. }
  302. if(!found){
  303. WriteStringToFile(fh,
  304. line
  305. );
  306. WriteStringToFile(fh,
  307. "\r\n"
  308. );
  309. BPFree(wdata);
  310. return 0;
  311. }
  312. hret = SafeArrayGetUBound(psa,
  313. 1,
  314. &uBound
  315. );
  316. if (hret != S_OK) {
  317. WriteStringToFile(fh,
  318. line
  319. );
  320. WriteStringToFile(fh,
  321. "\r\n"
  322. );
  323. return 0;
  324. }
  325. for(LONG i = 0;i <= uBound; i++){
  326. hret = SafeArrayGetElement(psa,
  327. &i,
  328. &pOSInst
  329. );
  330. if(hret != S_OK){
  331. BPFree(wdata);
  332. return -1;
  333. }
  334. hret = pOSInst->Get(L"Directory",
  335. 0,
  336. &v,
  337. &type,
  338. NULL
  339. );
  340. if(hret != WBEM_S_NO_ERROR){
  341. BPFree(wdata);
  342. pOSInst->Release();
  343. return -1;
  344. }
  345. if(v.vt != VT_BSTR){
  346. BPFree(wdata);
  347. pOSInst->Release();
  348. return -1;
  349. }
  350. if(wcscmp(v.bstrVal,wdata)){
  351. pOSInst->Release();
  352. VariantClear(&v);
  353. continue;
  354. }
  355. VariantClear(&v);
  356. // form the correct string.
  357. hret = pOSInst->Get(L"OperatingSystem",
  358. 0,
  359. &v,
  360. &type,
  361. NULL
  362. );
  363. if(hret != WBEM_S_NO_ERROR){
  364. BPFree(wdata);
  365. pOSInst->Release();
  366. return -1;
  367. }
  368. if(v.vt != VT_BSTR){
  369. BPFree(wdata);
  370. pOSInst->Release();
  371. return -1;
  372. }
  373. wlen = wcslen(v.bstrVal);
  374. slen = wlen*sizeof(WCHAR) + 1;
  375. str = (PCHAR) BPAlloc(slen);
  376. if (!str) {
  377. BPFree(wdata);
  378. pOSInst->Release();
  379. return -1;
  380. }
  381. len = WideCharToMultiByte(CP_ACP,
  382. 0,
  383. v.bstrVal,
  384. wlen,
  385. str,
  386. slen,
  387. NULL,
  388. NULL
  389. );
  390. *pchar=0;
  391. WriteStringToFile(fh,
  392. line
  393. );
  394. *pchar = '=';
  395. WriteStringToFile(fh,
  396. "="
  397. );
  398. WriteStringToFile(fh,
  399. str
  400. );
  401. BPFree(str);
  402. VariantClear(&v);
  403. hret = pOSInst->Get(L"Rest",
  404. 0,
  405. &v,
  406. &type,
  407. NULL
  408. );
  409. if(hret != WBEM_S_NO_ERROR){
  410. BPFree(wdata);
  411. pOSInst->Release();
  412. return -1;
  413. }
  414. if(v.vt != VT_BSTR){
  415. BPFree(wdata);
  416. pOSInst->Release();
  417. return -1;
  418. }
  419. wlen = wcslen(v.bstrVal);
  420. slen = wlen*sizeof(WCHAR) + 1;
  421. str = (PCHAR) BPAlloc(slen);
  422. if (!str) {
  423. BPFree(wdata);
  424. pOSInst->Release();
  425. return -1;
  426. }
  427. len = WideCharToMultiByte(CP_ACP,
  428. 0,
  429. v.bstrVal,
  430. wlen,
  431. str,
  432. slen,
  433. NULL,
  434. NULL
  435. );
  436. WriteStringToFile(fh,
  437. " "
  438. );
  439. WriteStringToFile(fh,
  440. str
  441. );
  442. BPFree(str);
  443. hret = pOSInst->Get(L"Redirect",
  444. 0,
  445. &v,
  446. &type,
  447. NULL
  448. );
  449. if(hret != WBEM_S_NO_ERROR){
  450. BPFree(wdata);
  451. pOSInst->Release();
  452. return -1;
  453. }
  454. if(v.vt != VT_BOOL){
  455. BPFree(wdata);
  456. pOSInst->Release();
  457. return -1;
  458. }
  459. if(v.boolVal && redir){// Loader also must be redirected
  460. WriteStringToFile(fh,
  461. " /redirect"
  462. );
  463. }
  464. VariantClear(&v);
  465. hret = pOSInst->Get(L"Fastdetect",
  466. 0,
  467. &v,
  468. &type,
  469. NULL
  470. );
  471. if(hret != WBEM_S_NO_ERROR){
  472. BPFree(wdata);
  473. pOSInst->Release();
  474. return -1;
  475. }
  476. if(v.vt != VT_BOOL){
  477. BPFree(wdata);
  478. pOSInst->Release();
  479. return -1;
  480. }
  481. if(v.boolVal){
  482. WriteStringToFile(fh,
  483. " /fastdetect"
  484. );
  485. }
  486. VariantClear(&v);
  487. hret = pOSInst->Get(L"Debug",
  488. 0,
  489. &v,
  490. &type,
  491. NULL
  492. );
  493. if(hret != WBEM_S_NO_ERROR){
  494. BPFree(wdata);
  495. pOSInst->Release();
  496. return -1;
  497. }
  498. if(v.vt != VT_BOOL){
  499. BPFree(wdata);
  500. pOSInst->Release();
  501. return -1;
  502. }
  503. if(v.boolVal){
  504. WriteStringToFile(fh,
  505. " /debug"
  506. );
  507. }
  508. VariantClear(&v);
  509. WriteStringToFile(fh,
  510. "\r\n"
  511. );
  512. pOSInst->Release();
  513. found = TRUE;
  514. if(i != uBound){
  515. // Shorten the array. After all u have a copy
  516. hret = SafeArrayGetElement(psa,
  517. &uBound,
  518. &pOSInst
  519. );
  520. if(hret != S_OK){
  521. BPFree(wdata);
  522. return -1;
  523. }
  524. hret = SafeArrayPutElement(psa,
  525. &i,
  526. pOSInst
  527. );
  528. pOSInst->Release();
  529. }
  530. sb.cElements = uBound;
  531. sb.lLbound = 0;
  532. hret = SafeArrayRedim(psa,
  533. &sb
  534. );
  535. uBound -= 1;
  536. i-=1; // so that the currently swapped element is looked at now.
  537. }
  538. if(!found){
  539. WriteStringToFile(fh,
  540. line
  541. );
  542. WriteStringToFile(fh,
  543. "\r\n"
  544. );
  545. }
  546. BPFree(wdata);
  547. return 0;
  548. }
  549. LONG
  550. SaveBootFile(IWbemClassObject *pInst,
  551. IWbemClassObject *pClass
  552. )
  553. {
  554. VARIANT v;
  555. VARIANT v1;
  556. BOOL redir;
  557. BOOL ret;
  558. DWORD dwlen;
  559. CIMTYPE type;
  560. HRESULT hret;
  561. PCHAR temp1,pchar;
  562. SAFEARRAY *org;
  563. temp1 = NULL;
  564. PCHAR fileName = GetBootFileName();
  565. HANDLE BootFile = GetFileHandle(fileName,OPEN_EXISTING, GENERIC_READ);
  566. BPFree(fileName);
  567. if (BootFile == INVALID_HANDLE_VALUE){
  568. return -1;
  569. }
  570. DWORD dwsize = GetFileSize(BootFile,
  571. NULL
  572. );
  573. if(dwsize == -1){
  574. CloseHandle(BootFile);
  575. return -1;
  576. }
  577. PCHAR data =(PCHAR) BPAlloc(dwsize + sizeof(CHAR));
  578. if(!data){
  579. return -1;
  580. }
  581. DWORD dwret = ReadFile(BootFile,
  582. (LPVOID) data,
  583. dwsize,
  584. &dwlen,
  585. NULL
  586. );
  587. if(dwret == 0){
  588. dwret = GetLastError();
  589. BPFree(data);
  590. CloseHandle(BootFile);
  591. return -1;
  592. }
  593. CloseHandle(BootFile);
  594. BootFile = GetFileHandle("boot.bak", TRUNCATE_EXISTING, GENERIC_WRITE);
  595. hret = pInst->Get(L"operating_systems",
  596. 0,
  597. &v,
  598. &type,
  599. NULL
  600. );
  601. if(hret != WBEM_S_NO_ERROR){
  602. BPFree(data);
  603. CloseHandle(BootFile);
  604. return -1;
  605. }
  606. VARTYPE t = VT_ARRAY|VT_UNKNOWN;
  607. if(v.vt != t){
  608. BPFree(data);
  609. CloseHandle(BootFile);
  610. return -1;
  611. }
  612. hret = SafeArrayCopy(v.parray, &org);
  613. if(hret != WBEM_S_NO_ERROR){
  614. BPFree(data);
  615. CloseHandle(BootFile);
  616. return -1;
  617. }
  618. hret = pInst->Get(L"Redirect",
  619. 0,
  620. &v1,
  621. &type,
  622. NULL
  623. );
  624. if(hret != WBEM_S_NO_ERROR){
  625. BPFree(data);
  626. CloseHandle(BootFile);
  627. return -1;
  628. }
  629. if(v1.vt != VT_BSTR){
  630. BPFree(data);
  631. CloseHandle(BootFile);
  632. return -1;
  633. }
  634. redir = FALSE;
  635. if(wcscmp(v1.bstrVal,L"no")){
  636. redir = TRUE;
  637. }
  638. CHAR sep[] = "\r\n";
  639. PCHAR temp = strtok(data, sep);
  640. while(temp){
  641. // ignore leading spaces
  642. while(*temp && (*temp == ' ')){
  643. temp ++;
  644. }
  645. if (strncmp(temp,"[boot loader]",strlen("[boot loader]"))==0) {
  646. // Ok, boot loader section. Write it.
  647. do{
  648. pchar = strchr(temp,'=');
  649. if((!pchar) ||(strncmp(temp,"default",strlen("default"))
  650. && strncmp(temp,"redirect",strlen("redirect"))
  651. && strncmp(temp,"timeout",strlen("timeout")))){
  652. // Write the default string
  653. WriteStringToFile(BootFile,temp);
  654. WriteStringToFile(BootFile,"\r\n");
  655. }
  656. if(strncmp(temp,"default",strlen("default")) == 0){
  657. // store the default string
  658. temp1 = temp;
  659. }
  660. temp = strtok(NULL, sep);
  661. }while(temp && (*temp != '['));
  662. if(WriteDefaultParams(pInst,data,temp1,v.parray,BootFile,v1.bstrVal)){
  663. BPFree(data);
  664. CloseHandle(BootFile);
  665. return -1;
  666. }
  667. continue;
  668. }
  669. if(strcmp(temp,"[operating systems]")==0){
  670. // dealing with the operating systems line
  671. // So get the Safe Array
  672. do{
  673. temp1 = temp;
  674. if(*temp1 != ';'){
  675. // comment line are ignored.
  676. pchar = strchr(temp,'=');
  677. if(pchar){
  678. if(WriteOSLine(BootFile,temp1, pchar, org ,v.parray, pClass,redir)){
  679. BPFree(data);
  680. CloseHandle(BootFile);
  681. return -1;
  682. }
  683. temp = strtok(NULL,sep);
  684. continue;
  685. }
  686. }
  687. WriteStringToFile(BootFile, temp);
  688. WriteStringToFile(BootFile,"\r\n");
  689. temp = strtok(NULL,sep);
  690. }while(temp && (*temp != '['));
  691. SafeArrayDestroy(org);
  692. VariantClear(&v);
  693. continue;
  694. }
  695. WriteStringToFile(BootFile,temp);
  696. WriteStringToFile(BootFile,"\r\n");
  697. temp = strtok(NULL,sep);
  698. }
  699. CloseHandle(BootFile);
  700. fileName = GetBootFileName();
  701. if(!fileName){
  702. return -1;
  703. }
  704. ret = CopyFile("boot.bak",
  705. fileName,
  706. FALSE
  707. );
  708. BPFree(fileName);
  709. return 0;
  710. }