Leaked source code of windows server 2003
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.

1797 lines
59 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. inf.c
  5. Abstract:
  6. Miscellaneous routines for the INF File Operation
  7. Author:
  8. Xiaofeng Zang (xiaoz) 17-Sep-2001 Created
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "StdAfx.h"
  13. #include "clmt.h"
  14. HRESULT RegistryRename(HINF hInf, LPTSTR lpszSection,HKEY hKeyRoot,LPTSTR lpszUser);
  15. HRESULT FolderMove(HINF hInf, LPTSTR lpszSection,BOOL bAnalyze);
  16. HRESULT ChangeServiceStartupType(LPCTSTR, DWORD, DWORD);
  17. HRESULT
  18. RegistryRename(HINF hInf, LPTSTR lpszSection,HKEY hKeyRoot,LPTSTR lpszUser)
  19. {
  20. UINT LineCount,LineNo;
  21. INFCONTEXT InfContext;
  22. DWORD dwStrType;
  23. LPTSTR pSubKeyPath;
  24. HKEY hKey;
  25. TCHAR szRenameType[MAX_PATH],szStringType[MAX_PATH];
  26. DWORD dwRenameType,dwStringType;
  27. DWORD cchMaxOldKeyPathLength = 0;
  28. DWORD cchMaxNewKeyPathLength = 0;
  29. DWORD cchMaxOldNameLength = 0;
  30. DWORD cchMaxNewNameLength = 0;
  31. DWORD cchMaxOldDataLength = 0;
  32. DWORD cchMaxNewDataLength = 0;
  33. DWORD dwAttrib = 0;
  34. LPTSTR lpszOldKey,lpszNewKey,lpszOldName,lpszNewName,lpszOldValue,lpszNewValue;
  35. HRESULT hr;
  36. LONG lstatus;
  37. lpszOldKey = lpszNewKey = lpszOldName = lpszNewName
  38. = lpszOldValue = lpszNewValue = NULL;
  39. LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
  40. if ((LONG)LineCount < 0)
  41. {
  42. hr = S_FALSE;
  43. DPF(INFwar ,TEXT("section name %s is empty failed !"),lpszSection);
  44. goto Cleanup;
  45. }
  46. for (LineNo = 0; LineNo < LineCount; LineNo++)
  47. {
  48. DWORD cchTmpOldKeyPathLength,cchTmpNewKeyPathLength ,cchTmpOldNameLength ,
  49. cchTmpNewNameLength,cchTmpOldDataLength,cchTmpNewDataLength;
  50. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  51. {
  52. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
  53. continue;
  54. }
  55. if (!SetupGetStringField(&InfContext,1,szRenameType,MAX_PATH,NULL))
  56. {
  57. DPF(INFwar ,TEXT("get [%s] 's line %n 's Field 0 failed !"),lpszSection, LineNo);
  58. continue;
  59. }
  60. cchTmpOldKeyPathLength = cchTmpNewKeyPathLength = cchTmpOldNameLength
  61. = cchTmpNewNameLength = cchTmpOldDataLength = cchTmpNewDataLength = 0;
  62. dwRenameType = _tstoi(szRenameType);
  63. switch (dwRenameType)
  64. {
  65. case TYPE_VALUE_RENAME:
  66. if (!SetupGetStringField(&InfContext,2,szStringType,MAX_PATH,NULL)
  67. || !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpOldKeyPathLength)
  68. || !SetupGetStringField(&InfContext,4,NULL,0,&cchTmpOldNameLength)
  69. || ! SetupGetStringField(&InfContext,5,NULL,0,&cchTmpOldDataLength)
  70. || ! SetupGetStringField(&InfContext,6,NULL,0,&cchTmpNewDataLength))
  71. {
  72. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3,4,5,6 failed !"),lpszSection ,InfContext.Line);
  73. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  74. goto Cleanup;
  75. }
  76. break;
  77. case TYPE_VALUENAME_RENAME:
  78. if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldKeyPathLength)
  79. || !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpOldNameLength)
  80. || ! SetupGetStringField(&InfContext,4,NULL,0,&cchTmpNewNameLength))
  81. {
  82. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4,5 failed !"),lpszSection ,InfContext.Line);
  83. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  84. goto Cleanup;
  85. }
  86. break;
  87. case TYPE_KEY_RENAME:
  88. if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldKeyPathLength)
  89. || !SetupGetStringField(&InfContext,3,NULL,0,&cchTmpNewKeyPathLength))
  90. {
  91. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4 failed !"),lpszSection ,InfContext.Line);
  92. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  93. goto Cleanup;
  94. }
  95. break;
  96. }
  97. cchMaxOldKeyPathLength = max(cchTmpOldKeyPathLength,cchMaxOldKeyPathLength);
  98. cchMaxNewKeyPathLength = max(cchTmpNewKeyPathLength,cchMaxNewKeyPathLength);
  99. cchMaxOldNameLength = max(cchTmpOldNameLength,cchMaxOldNameLength);
  100. cchMaxNewNameLength = max(cchTmpNewNameLength,cchMaxNewNameLength);
  101. cchMaxOldDataLength = max(cchTmpOldDataLength,cchMaxOldDataLength);
  102. cchMaxNewDataLength = max(cchTmpNewDataLength,cchMaxNewDataLength);
  103. }
  104. if (cchMaxOldKeyPathLength)
  105. {
  106. if (!(lpszOldKey = malloc(++cchMaxOldKeyPathLength * sizeof(TCHAR))))
  107. {
  108. hr = E_OUTOFMEMORY;
  109. goto Cleanup;
  110. }
  111. }
  112. if (cchMaxNewKeyPathLength)
  113. {
  114. if (!(lpszNewKey = malloc(++cchMaxNewKeyPathLength * sizeof(TCHAR))))
  115. {
  116. hr = E_OUTOFMEMORY;
  117. goto Cleanup;
  118. }
  119. }
  120. if (cchMaxOldNameLength)
  121. {
  122. if (!(lpszOldName = malloc(++cchMaxOldNameLength * sizeof(TCHAR))))
  123. {
  124. hr = E_OUTOFMEMORY;
  125. goto Cleanup;
  126. }
  127. }
  128. if (cchMaxNewNameLength)
  129. {
  130. if (!(lpszNewName = malloc(++cchMaxNewNameLength * sizeof(TCHAR))))
  131. {
  132. hr = E_OUTOFMEMORY;
  133. goto Cleanup;
  134. }
  135. }
  136. if (cchMaxOldDataLength)
  137. {
  138. if (!(lpszOldValue = malloc(++cchMaxOldDataLength * sizeof(TCHAR))))
  139. {
  140. hr = E_OUTOFMEMORY;
  141. goto Cleanup;
  142. }
  143. }
  144. if (cchMaxNewDataLength)
  145. {
  146. if (!(lpszNewValue = malloc(++cchMaxNewDataLength * sizeof(TCHAR))))
  147. {
  148. hr = E_OUTOFMEMORY;
  149. goto Cleanup;
  150. }
  151. }
  152. for (LineNo = 0; LineNo < LineCount; LineNo++)
  153. {
  154. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  155. {
  156. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
  157. continue;
  158. }
  159. if (!SetupGetStringField(&InfContext,1,szRenameType,MAX_PATH,NULL))
  160. {
  161. DPF(INFwar ,TEXT("get [%s] 's line %n 's Field 0 failed !"),lpszSection, LineNo);
  162. continue;
  163. }
  164. dwRenameType = _tstoi(szRenameType);
  165. switch (dwRenameType)
  166. {
  167. case TYPE_VALUE_RENAME:
  168. if (!SetupGetStringField(&InfContext,2,szStringType,MAX_PATH,NULL)
  169. || !SetupGetStringField(&InfContext,3,lpszOldKey,cchMaxOldKeyPathLength,NULL)
  170. || ! SetupGetStringField(&InfContext,4,lpszOldName,cchMaxOldNameLength,NULL)
  171. || ! SetupGetStringField(&InfContext,5,lpszOldValue,cchMaxOldDataLength,NULL)
  172. || ! SetupGetStringField(&InfContext,6,lpszNewValue ,cchMaxNewDataLength,NULL))
  173. {
  174. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field ,3,4,5 failed !"),lpszSection ,InfContext.Line);
  175. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  176. goto Cleanup;
  177. }
  178. if (!Str2KeyPath(lpszOldKey,&hKey,&pSubKeyPath))
  179. {
  180. DPF(INFerr ,TEXT("format errorin line %d: %s !"),LineNo,lpszOldKey);
  181. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  182. goto Cleanup;
  183. }
  184. if (hKeyRoot)
  185. {
  186. hKey = hKeyRoot;
  187. }
  188. dwStringType = _tstoi(szStringType);
  189. lstatus = RegResetValue(hKey, pSubKeyPath,lpszOldName,dwStringType,lpszOldValue,lpszOldValue, 0, NULL);
  190. if (lstatus == ERROR_SUCCESS)
  191. {
  192. hr = AddRegValueRename(pSubKeyPath,lpszOldName,NULL,lpszOldValue,lpszNewValue,dwStringType,dwAttrib,lpszUser);
  193. //Add error checking here
  194. }
  195. break;
  196. case TYPE_VALUENAME_RENAME:
  197. break;
  198. case TYPE_KEY_RENAME:
  199. break;
  200. }
  201. }
  202. Cleanup:
  203. FreePointer(lpszOldKey);
  204. FreePointer(lpszNewKey);
  205. FreePointer(lpszOldName);
  206. FreePointer(lpszNewName);
  207. FreePointer(lpszOldValue);
  208. FreePointer(lpszNewValue);
  209. return hr;
  210. }
  211. HRESULT FolderMove(HINF hInf, LPTSTR lpszSection,BOOL bAnalyze)
  212. {
  213. LPTSTR lpszOldFolder = NULL,lpszNewFolder = NULL,lpExcludeFileList = NULL;
  214. DWORD cchMaxOldFolderSize = 0,cchMaxNewFolderSize = 0,cchMaxExcludeFileListSize = 0;
  215. HRESULT hr;
  216. UINT LineCount,LineNo;
  217. INFCONTEXT InfContext;
  218. TCHAR szType[MAX_PATH];
  219. DWORD dwType;
  220. if( (hInf == INVALID_HANDLE_VALUE) || (!lpszSection) )
  221. {
  222. hr = E_INVALIDARG;
  223. goto Cleanup;
  224. }
  225. LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
  226. if ((LONG)LineCount < 0)
  227. {
  228. hr = S_FALSE;
  229. DPF(INFwar ,TEXT("section name %s is empty failed !"),lpszSection);
  230. goto Cleanup;
  231. }
  232. for (LineNo = 0; LineNo < LineCount; LineNo++)
  233. {
  234. DWORD cchTmpOldFolderSize = 0,cchTmpNewFolderSize = 0,cchTmpExcludeFileListSize = 0;
  235. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  236. {
  237. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
  238. continue;
  239. }
  240. if (!SetupGetStringField(&InfContext,1,szType,MAX_PATH,NULL))
  241. {
  242. DPF(INFwar ,TEXT("get [%s] 's line %d 's Field 0 failed !"),lpszSection, LineNo);
  243. continue;
  244. }
  245. dwType = _tstoi(szType);
  246. switch (dwType)
  247. {
  248. case TYPE_SFPFILE_MOVE:
  249. case TYPE_FILE_MOVE:
  250. case TYPE_DIR_MOVE:
  251. if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpOldFolderSize)
  252. || ! SetupGetStringField(&InfContext,3,NULL,0,&cchTmpNewFolderSize))
  253. {
  254. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  255. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3failed !"),lpszSection ,LineNo);
  256. goto Cleanup;
  257. }
  258. if (TYPE_DIR_MOVE == dwType)
  259. {
  260. BOOL bTmp;
  261. bTmp = SetupGetMultiSzField(&InfContext,4,NULL,0,&cchTmpExcludeFileListSize);
  262. if (!( bTmp && (cchTmpExcludeFileListSize >= sizeof(TCHAR))))
  263. {
  264. cchTmpExcludeFileListSize = 0;
  265. }
  266. }
  267. break;
  268. default:
  269. DPF(INFerr ,TEXT(" [%s] 's line %d 's Field 1 invalid value !"),lpszSection, LineNo);
  270. hr = E_FAIL;
  271. goto Cleanup;
  272. break;
  273. }
  274. cchMaxOldFolderSize = max(cchTmpOldFolderSize,cchMaxOldFolderSize);
  275. cchMaxNewFolderSize = max(cchTmpNewFolderSize,cchMaxNewFolderSize);
  276. cchMaxExcludeFileListSize = max(cchTmpExcludeFileListSize,cchMaxExcludeFileListSize);
  277. }
  278. if (cchMaxOldFolderSize)
  279. { // add one more TCHAR space incase the file is SFPed in which case we need
  280. // provide a multisz string to UnProtectSFPFiles
  281. cchMaxOldFolderSize += 2;
  282. if (!(lpszOldFolder = malloc(cchMaxOldFolderSize * sizeof(TCHAR))))
  283. {
  284. hr = E_OUTOFMEMORY;
  285. goto Cleanup;
  286. }
  287. }
  288. if (cchMaxNewFolderSize)
  289. {
  290. if (!(lpszNewFolder = malloc(++cchMaxNewFolderSize * sizeof(TCHAR))))
  291. {
  292. hr = E_OUTOFMEMORY;
  293. goto Cleanup;
  294. }
  295. }
  296. if (cchMaxExcludeFileListSize)
  297. {
  298. if (!(lpExcludeFileList = malloc(++cchMaxExcludeFileListSize * sizeof(TCHAR))))
  299. {
  300. hr = E_OUTOFMEMORY;
  301. goto Cleanup;
  302. }
  303. }
  304. for (LineNo = 0; LineNo < LineCount; LineNo++)
  305. {
  306. LPTSTR lpTmpExcludeList = NULL;
  307. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  308. {
  309. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSection);
  310. continue;
  311. }
  312. if (!SetupGetStringField(&InfContext,1,szType,MAX_PATH,NULL))
  313. {
  314. DPF(INFwar ,TEXT("get [%s] 's line %d 's Field 0 failed !"),lpszSection, LineNo);
  315. continue;
  316. }
  317. dwType = _tstoi(szType);
  318. if (!SetupGetStringField(&InfContext,2,lpszOldFolder,cchMaxOldFolderSize,NULL)
  319. || ! SetupGetStringField(&InfContext,3,lpszNewFolder,cchMaxNewFolderSize,NULL))
  320. {
  321. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  322. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2,3failed !"),lpszSection ,LineNo);
  323. goto Cleanup;
  324. }
  325. switch (dwType)
  326. {
  327. case TYPE_DIR_MOVE:
  328. if (cchMaxExcludeFileListSize)
  329. {
  330. DWORD dwSize;
  331. BOOL bTmp = SetupGetMultiSzField(&InfContext,4,lpExcludeFileList,
  332. cchMaxExcludeFileListSize,&dwSize);
  333. if (!( bTmp && dwSize >= sizeof(TCHAR)))
  334. {
  335. lpTmpExcludeList = lpExcludeFileList;
  336. }
  337. }
  338. else
  339. {
  340. lpTmpExcludeList = NULL;
  341. }
  342. case TYPE_SFPFILE_MOVE:
  343. case TYPE_FILE_MOVE:
  344. if (bAnalyze)
  345. {
  346. AddFolderRename(lpszOldFolder,lpszNewFolder,dwType,lpTmpExcludeList);
  347. }
  348. else
  349. {
  350. if (lpTmpExcludeList)
  351. {
  352. LPTSTR lp = lpTmpExcludeList;
  353. while (*lp)
  354. {
  355. if (!MoveFileEx(lp,NULL,MOVEFILE_DELAY_UNTIL_REBOOT))
  356. {
  357. DWORD dw = GetLastError();
  358. DPF(INFerr, TEXT("MoveFileEx(delete) failed %s,win32 error = %d"),lp,dw);
  359. }
  360. lp += (lstrlen(lp)+1);
  361. }
  362. }
  363. if (dwType == TYPE_SFPFILE_MOVE)
  364. {
  365. lpszOldFolder[lstrlen(lpszOldFolder)+1] = TEXT('\0');
  366. UnProtectSFPFiles(lpszOldFolder,NULL);
  367. }
  368. if (!MoveFileEx(lpszOldFolder,lpszNewFolder,MOVEFILE_DELAY_UNTIL_REBOOT))
  369. {
  370. DWORD dw = GetLastError();
  371. DPF(INFerr, TEXT("MoveFileEx(%s,%s) failed win32 error = %d"),lpszOldFolder,lpszNewFolder,dw);
  372. }
  373. }
  374. break;
  375. }
  376. }
  377. Cleanup:
  378. FreePointer(lpszOldFolder);
  379. FreePointer(lpszNewFolder);
  380. FreePointer(lpExcludeFileList);
  381. return hr;
  382. }
  383. HRESULT EnsureDoItemInfFile(
  384. LPTSTR lpszInfFile,
  385. size_t CchBufSize)
  386. {
  387. LPWSTR lpszHeader = L"[Version]\r\nsignature=\"$Windows NT$\"\r\nClassGUID={00000000-0000-0000-0000-000000000000}\r\nlayoutfile=LAYOUT.INF\r\n";
  388. HANDLE hFile = INVALID_HANDLE_VALUE;
  389. HRESULT hr = S_OK;
  390. DWORD dwWritten;
  391. DWORD dwStatusinReg;
  392. BOOL bCureMode = FALSE;
  393. WORD wBOM=0xFEFF;
  394. SECURITY_ATTRIBUTES sa;
  395. PSECURITY_DESCRIPTOR pSD = NULL;
  396. if (!GetSystemWindowsDirectory(lpszInfFile, CchBufSize))
  397. {
  398. hr = HRESULT_FROM_WIN32(GetLastError());
  399. DPF(INFerr, TEXT("Failed to get system directory, hr = 0x%X"), hr);
  400. goto Exit;
  401. }
  402. if (!ConcatenatePaths(lpszInfFile,CLMT_BACKUP_DIR,CchBufSize))
  403. {
  404. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  405. DPF(INFerr, TEXT("buffer size too small when creating clmtdo.inf"));
  406. goto Exit;
  407. }
  408. if (!ConcatenatePaths(lpszInfFile,TEXT("CLMTDO.INF"),CchBufSize))
  409. {
  410. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  411. DPF(INFerr, TEXT("buffer size too small when creating clmtdo.inf"));
  412. goto Exit;
  413. }
  414. hr = CLMTGetMachineState(&dwStatusinReg);
  415. //If we 've done running clmt.exe and called again, usually it's in /cure mode...
  416. //on this case, we will append the INF file
  417. if ( (hr != S_OK)
  418. || ( (CLMT_STATE_MIGRATION_DONE != dwStatusinReg)
  419. && (CLMT_STATE_FINISH != dwStatusinReg)
  420. && (CLMT_STATE_PROGRAMFILES_CURED != dwStatusinReg)) )
  421. {
  422. hr = CreateAdminsSd(&pSD);
  423. if (hr != S_OK)
  424. {
  425. goto Exit;
  426. }
  427. sa.nLength = sizeof(sa);
  428. sa.bInheritHandle = FALSE;
  429. sa.lpSecurityDescriptor = pSD;
  430. hFile = CreateFile(lpszInfFile,GENERIC_WRITE|GENERIC_READ,0,
  431. &sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  432. hr = InitChangeLog();
  433. }
  434. else
  435. {
  436. bCureMode = TRUE;
  437. hFile = CreateFile(lpszInfFile,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  438. }
  439. if (INVALID_HANDLE_VALUE == hFile)
  440. {
  441. DWORD dw = GetLastError();
  442. hr = HRESULT_FROM_WIN32(GetLastError());
  443. DPF(INFerr, TEXT("Create file %s failed with hr = 0x%X"),lpszInfFile,hr);
  444. goto Exit;
  445. }
  446. if (!bCureMode)
  447. {
  448. if(! WriteFile(hFile,&wBOM,sizeof(WORD),&dwWritten,NULL))
  449. {
  450. hr = HRESULT_FROM_WIN32(GetLastError());
  451. DPF(INFerr, TEXT("write to file %s failed with hr = 0x%X"),lpszInfFile,hr);
  452. goto Exit;
  453. }
  454. if(! WriteFile(hFile,lpszHeader,lstrlenW(lpszHeader)*sizeof(TCHAR),&dwWritten,NULL))
  455. {
  456. hr = HRESULT_FROM_WIN32(GetLastError());
  457. DPF(INFerr, TEXT("write to file %s failed with hr = 0x%X"),lpszInfFile,hr);
  458. goto Exit;
  459. }
  460. }
  461. Exit:
  462. if (INVALID_HANDLE_VALUE != hFile)
  463. {
  464. CloseHandle(hFile);
  465. }
  466. if (pSD)
  467. {
  468. LocalFree(pSD);
  469. }
  470. return hr;
  471. }
  472. HRESULT GetMaxLenEachField(
  473. HINF hInf,
  474. LPTSTR lpSection,
  475. BOOL bExitOnError,
  476. DWORD dwMinFieldCount,
  477. DWORD dwMaxFieldCount,
  478. PDWORD pdwFieldValidFlag,
  479. PDWORD pdwSizeRequired,
  480. BOOL bMultiSZ
  481. )
  482. {
  483. HRESULT hr;
  484. UINT LineCount,LineNo;
  485. UINT nFieldCount, nFieldIndex;
  486. INFCONTEXT InfContext;
  487. UINT i;
  488. UINT cchReqSize;
  489. if( (hInf == INVALID_HANDLE_VALUE) || !lpSection )
  490. {
  491. hr = E_INVALIDARG;
  492. goto Exit;
  493. }
  494. if (!dwMinFieldCount || !dwMaxFieldCount
  495. || ( dwMaxFieldCount < dwMinFieldCount)
  496. || !pdwSizeRequired)
  497. {
  498. hr = E_INVALIDARG;
  499. goto Exit;
  500. }
  501. for (i = 0; i < dwMaxFieldCount; i++)
  502. {
  503. pdwSizeRequired[i] = 0;
  504. }
  505. LineCount = (UINT)SetupGetLineCount(hInf,lpSection);
  506. if ((LONG)LineCount < 0)
  507. {
  508. hr = S_FALSE;
  509. DPF(INFwar ,TEXT("section name %s is empty failed !"),lpSection);
  510. goto Exit;
  511. }
  512. for (LineNo = 0; LineNo < LineCount; LineNo++)
  513. {
  514. DWORD dwNumField;
  515. if (!SetupGetLineByIndex(hInf,lpSection,LineNo,&InfContext))
  516. {
  517. if (bExitOnError)
  518. {
  519. hr = HRESULT_FROM_WIN32(GetLastError());
  520. goto Exit;
  521. }
  522. else
  523. {
  524. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
  525. continue;
  526. }
  527. }
  528. dwNumField = SetupGetFieldCount(&InfContext);
  529. if ( (dwNumField < dwMinFieldCount) || (dwNumField > dwMaxFieldCount) )
  530. {
  531. if (bExitOnError)
  532. {
  533. hr = HRESULT_FROM_WIN32(GetLastError());
  534. goto Exit;
  535. }
  536. else
  537. {
  538. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
  539. continue;
  540. }
  541. }
  542. for (nFieldIndex = 1 ; nFieldIndex <= dwNumField ; nFieldIndex++)
  543. {
  544. BOOL bRet;
  545. if (pdwFieldValidFlag && !pdwFieldValidFlag[nFieldIndex])
  546. {
  547. continue;
  548. }
  549. if ((nFieldIndex == dwMaxFieldCount) && bMultiSZ)
  550. {
  551. bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
  552. }
  553. else
  554. {
  555. bRet = SetupGetStringField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
  556. }
  557. if (!bRet)
  558. {
  559. if (bExitOnError)
  560. {
  561. hr = HRESULT_FROM_WIN32(GetLastError());
  562. goto Exit;
  563. }
  564. else
  565. {
  566. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpSection);
  567. continue;
  568. }
  569. }
  570. pdwSizeRequired[nFieldIndex-1] = max(pdwSizeRequired[nFieldIndex-1],cchReqSize);
  571. }
  572. }
  573. hr = S_OK;
  574. Exit:
  575. return hr;
  576. }
  577. HRESULT RegUpdate(HINF hInf, HKEY hKeyUser , LPTSTR lpszUsersid)
  578. {
  579. #define REG_UPDATE_FIELD_COUNT 5
  580. HRESULT hr;
  581. LPTSTR lpszSectionName = NULL;
  582. DWORD cChSecBuffeSize, dwRequestSize = 0;
  583. LPTSTR lpszSectionSuffix = NULL;
  584. UINT LineCount,LineNo,nFieldIndex;
  585. INFCONTEXT InfContext;
  586. TCHAR szRegUpdateType[MAX_PATH],szStrType[MAX_PATH];
  587. DWORD dwRegUpdateType,dwStrType;
  588. LPTSTR lpszField[REG_UPDATE_FIELD_COUNT+1] = {NULL, szRegUpdateType, NULL, NULL, NULL, NULL};
  589. HKEY hKey;
  590. LPTSTR lpSubKey;
  591. DWORD pdwSizeRequired[REG_UPDATE_FIELD_COUNT+1] = {0,MAX_PATH,0,0,0,0};
  592. int i;
  593. //check the INF file handle
  594. if(hInf == INVALID_HANDLE_VALUE)
  595. {
  596. hr = E_INVALIDARG;
  597. goto Cleanup;
  598. }
  599. if (!lpszUsersid || !MyStrCmpI(lpszUsersid,TEXT("Default_User_SID")))
  600. {
  601. //If user sid is NULL it means default user
  602. cChSecBuffeSize = lstrlen(TEXT("REG.Update.Default User")) + 1 ;
  603. lpszSectionSuffix = DEFAULT_USER;
  604. }
  605. else if (!lpszUsersid[0])
  606. {
  607. //If user sid is "", it means system wide regsitry
  608. cChSecBuffeSize = lstrlen(TEXT("REG.Update.Sys")) + 1 ;
  609. lpszSectionSuffix = TEXT("SYS");
  610. } else
  611. {
  612. //If it's normal user , the section name is "REG.Update.%userSID%"
  613. cChSecBuffeSize = lstrlen(TEXT("REG.Update.")) + lstrlen(lpszUsersid)+2;
  614. }
  615. //Alloc memory and contruct the section name
  616. if (!(lpszSectionName = (LPTSTR) malloc(cChSecBuffeSize * sizeof(TCHAR))))
  617. {
  618. hr = E_OUTOFMEMORY;
  619. goto Cleanup;
  620. }
  621. if (lpszSectionSuffix)
  622. {
  623. if (FAILED(StringCchPrintf(lpszSectionName,cChSecBuffeSize,TEXT("%s%s"),TEXT("REG.Update."),
  624. lpszSectionSuffix)))
  625. {
  626. hr = E_FAIL;
  627. goto Cleanup;
  628. }
  629. }
  630. else
  631. {
  632. if (FAILED(StringCchPrintf(lpszSectionName,cChSecBuffeSize,TEXT("%s%s"),TEXT("REG.Update."),
  633. lpszUsersid)))
  634. {
  635. hr = E_FAIL;
  636. goto Cleanup;
  637. }
  638. }
  639. //here we got the section name and then try to get how many lines there
  640. LineCount = (UINT)SetupGetLineCount(hInf,lpszSectionName);
  641. if ((LONG)LineCount < 0)
  642. {
  643. //BUGBUG: xiaoz:The error value here needs to be revisted
  644. hr = E_FAIL;
  645. goto Cleanup;
  646. }
  647. //Scan the INF file section to get the max buf required for each field
  648. for (LineNo = 0; LineNo < LineCount; LineNo++)
  649. {
  650. DWORD dwNumField;
  651. DWORD dwDataStart;
  652. if (!SetupGetLineByIndex(hInf,lpszSectionName,LineNo,&InfContext))
  653. {
  654. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
  655. continue;
  656. }
  657. dwNumField = SetupGetFieldCount(&InfContext);
  658. if ( dwNumField < 4 )
  659. {
  660. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
  661. continue;
  662. }
  663. if (!SetupGetStringField(&InfContext,1,lpszField[1],pdwSizeRequired[1],NULL))
  664. {
  665. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
  666. continue;
  667. }
  668. dwRegUpdateType = _tstoi(lpszField[1]);
  669. switch (dwRegUpdateType)
  670. {
  671. case CONSTANT_REG_VALUE_DATA_RENAME:
  672. if (!SetupGetStringField(&InfContext,2,szStrType,ARRAYSIZE(szStrType),NULL))
  673. {
  674. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
  675. continue;
  676. }
  677. dwStrType = _tstoi(szStrType);
  678. dwDataStart = 3;
  679. break;
  680. case CONSTANT_REG_VALUE_NAME_RENAME:
  681. case CONSTANT_REG_KEY_RENAME:
  682. dwDataStart = 2;
  683. break;
  684. }
  685. for (nFieldIndex = dwDataStart ; nFieldIndex <= min(dwNumField,REG_UPDATE_FIELD_COUNT) ; nFieldIndex++)
  686. {
  687. BOOL bRet;
  688. DWORD cchReqSize;
  689. if ((nFieldIndex == REG_UPDATE_FIELD_COUNT) && (dwStrType == REG_MULTI_SZ))
  690. {
  691. bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
  692. }
  693. else
  694. {
  695. bRet = SetupGetMultiSzField(&InfContext,nFieldIndex,NULL,0,&cchReqSize);
  696. }
  697. if (!bRet)
  698. {
  699. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpszSectionName);
  700. continue;
  701. }
  702. pdwSizeRequired[nFieldIndex] = max(pdwSizeRequired[nFieldIndex],cchReqSize);
  703. }
  704. }
  705. for (i = 2; i<= REG_UPDATE_FIELD_COUNT; i++)
  706. {
  707. if (pdwSizeRequired[i])
  708. {
  709. if ( NULL == (lpszField[i] = malloc(++pdwSizeRequired[i] * sizeof(TCHAR))))
  710. {
  711. hr = E_OUTOFMEMORY;
  712. goto Cleanup;
  713. }
  714. }
  715. }
  716. for(LineNo=0; LineNo<LineCount; LineNo++)
  717. {
  718. SetupGetLineByIndex(hInf,lpszSectionName,LineNo,&InfContext);
  719. SetupGetStringField(&InfContext,1,lpszField[1],pdwSizeRequired[1],NULL);
  720. dwRegUpdateType = _tstoi(lpszField[1]);
  721. switch (dwRegUpdateType)
  722. {
  723. case CONSTANT_REG_VALUE_DATA_RENAME:
  724. SetupGetStringField(&InfContext,2,szStrType,ARRAYSIZE(szStrType),NULL);
  725. dwStrType = _tstoi(szStrType);
  726. SetupGetStringField(&InfContext,3,lpszField[3],pdwSizeRequired[3],NULL);
  727. SetupGetStringField(&InfContext,4,lpszField[4],pdwSizeRequired[4],NULL);
  728. if ((dwStrType & 0xffff) == REG_MULTI_SZ)
  729. {
  730. SetupGetMultiSzField(&InfContext,5,lpszField[5],pdwSizeRequired[5],NULL);
  731. }
  732. else if ((dwStrType & 0xffff) == REG_BINARY)
  733. {
  734. if (!SetupGetBinaryField(&InfContext,5,(LPBYTE)lpszField[5],pdwSizeRequired[5]*sizeof(TCHAR),&dwRequestSize) &&
  735. GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  736. {
  737. free(lpszField[5]);
  738. if ((lpszField[5] = (LPTSTR)malloc(dwRequestSize)) == NULL)
  739. {
  740. hr = E_OUTOFMEMORY;
  741. goto Cleanup;
  742. }
  743. SetupGetBinaryField(&InfContext,5,(LPBYTE)lpszField[5],dwRequestSize,NULL);
  744. }
  745. }
  746. else
  747. {
  748. SetupGetStringField(&InfContext,5,lpszField[5],pdwSizeRequired[5],NULL);
  749. }
  750. if (!(*lpszField[3]))
  751. {
  752. lpSubKey = NULL;
  753. }
  754. else
  755. {
  756. Str2KeyPath(lpszField[3],&hKey,&lpSubKey);
  757. }
  758. if (hKeyUser)
  759. {
  760. hKey = hKeyUser;
  761. }
  762. if ( (dwStrType & 0xffff) == REG_DWORD)
  763. {
  764. MyRegSetDWValue(hKey,lpSubKey,lpszField[4],lpszField[5]);
  765. }
  766. else
  767. {
  768. RegResetValue(hKey,lpSubKey,lpszField[4],dwStrType,TEXT(""),lpszField[5],dwRequestSize,lpszUsersid);
  769. }
  770. break;
  771. case CONSTANT_REG_VALUE_NAME_RENAME:
  772. case CONSTANT_REG_KEY_RENAME:
  773. for (i = 2; i <= 4 ;i++)
  774. {
  775. SetupGetStringField(&InfContext,i,lpszField[i],pdwSizeRequired[i],NULL);
  776. }
  777. Str2KeyPath(lpszField[2],&hKey,&lpSubKey);
  778. if (hKeyUser)
  779. {
  780. hKey = hKeyUser;
  781. }
  782. if (dwRegUpdateType == CONSTANT_REG_VALUE_NAME_RENAME)
  783. {
  784. RegResetValueName(hKey,lpSubKey,lpszField[3],lpszField[4], lpszUsersid);
  785. }
  786. else
  787. {
  788. RegResetKeyName(hKey, lpSubKey, lpszField[3], lpszField[4]);
  789. }
  790. break;
  791. }
  792. }
  793. hr = S_OK;
  794. Cleanup:
  795. FreePointer(lpszSectionName);
  796. for (i = 2; i< ARRAYSIZE(lpszField); i++)
  797. {
  798. FreePointer(lpszField[i]);
  799. }
  800. return hr;
  801. }
  802. HRESULT INFCreateHardLink(
  803. HINF hInf,
  804. LPTSTR lpszSection,
  805. BOOL bMakeLinkHidden)
  806. {
  807. HRESULT hr;
  808. INT LineCount,LineNo,nFieldIndex;
  809. INFCONTEXT InfContext;
  810. TCHAR szFileName[MAX_PATH+1],szExistingFileName[MAX_PATH+1],szHidden[MAX_PATH];
  811. TCHAR szType[10];
  812. DWORD dwType;
  813. TCHAR lpszInf[MAX_PATH+1];
  814. HINF hMyInf;
  815. BOOL bLocalHidden = bMakeLinkHidden;
  816. //check the INF file handle
  817. hMyInf = hInf;
  818. if(hMyInf == INVALID_HANDLE_VALUE)
  819. {
  820. hr = EnsureDoItemInfFile(lpszInf,ARRAYSIZE(lpszInf));
  821. if (FAILED(hr))
  822. {
  823. goto Cleanup;
  824. }
  825. hMyInf = SetupOpenInfFile(lpszInf,
  826. NULL,
  827. INF_STYLE_WIN4,
  828. NULL);
  829. if (hMyInf == INVALID_HANDLE_VALUE)
  830. {
  831. hr = E_INVALIDARG;
  832. goto Cleanup;
  833. }
  834. }
  835. LineCount = (UINT)SetupGetLineCount(hMyInf,lpszSection);
  836. if ((LONG)LineCount < 0)
  837. {
  838. hr = S_FALSE;
  839. goto Cleanup;
  840. }
  841. for (LineNo = LineCount -1 ; LineNo >= 0; LineNo--)
  842. {
  843. BOOL b1,b2,b3,b4;
  844. if (!SetupGetLineByIndex(hMyInf,lpszSection,LineNo,&InfContext))
  845. {
  846. continue;
  847. }
  848. b1 = SetupGetStringField(&InfContext,1,szType,ARRAYSIZE(szType),NULL);
  849. b2 = SetupGetStringField(&InfContext,2,szFileName,ARRAYSIZE(szFileName),NULL);
  850. b3 = SetupGetStringField(&InfContext,3,szExistingFileName,ARRAYSIZE(szExistingFileName),NULL);
  851. if (!b1 || !b2 || !b3)
  852. {
  853. continue;
  854. }
  855. b4 = SetupGetStringField(&InfContext,4,szHidden,ARRAYSIZE(szHidden),NULL);
  856. bLocalHidden = bMakeLinkHidden;
  857. if (b4)
  858. {
  859. DWORD dwHiddenType;
  860. dwHiddenType = _tstoi(szHidden);
  861. if (!dwHiddenType)
  862. {
  863. bLocalHidden = FALSE;
  864. }
  865. else
  866. {
  867. bLocalHidden = TRUE;
  868. }
  869. }
  870. dwType = _tstoi(szType);
  871. #ifdef CREATE_MINI_HARDLIN
  872. if (g_dwRunningStatus == CLMT_CURE_PROGRAM_FILES)
  873. {
  874. if (dwType == 0)
  875. {
  876. continue;
  877. }
  878. }
  879. #endif
  880. #ifdef CONSOLE_UI
  881. wprintf(TEXT("create reparse point between folder %s and %s\n"),szFileName,szExistingFileName);
  882. #endif
  883. if (CreateSymbolicLink(szFileName,szExistingFileName,bLocalHidden))
  884. {
  885. //hr = S_OK;
  886. }
  887. else
  888. {
  889. //hr = HRESULT_FROM_WIN32(GetLastError());
  890. }
  891. }
  892. hr = S_OK;
  893. Cleanup:
  894. if ( (hInf == INVALID_HANDLE_VALUE) && (hMyInf != INVALID_HANDLE_VALUE) )
  895. {
  896. SetupCloseInfFile(hMyInf);
  897. }
  898. return hr;
  899. }
  900. //-----------------------------------------------------------------------
  901. //
  902. // Function: AnalyzeServicesStatus
  903. //
  904. // Descrip: Analyze the services running on the system and see if
  905. // they need to be stopped or not
  906. //
  907. // Returns: S_OK if function succeeded.
  908. // else if error occured
  909. //
  910. // Notes: none
  911. //
  912. // History: 04/30/2002 rerkboos created
  913. // 07/08/2002 rerkboos modified
  914. // 09/06/2002 rerkboos modified
  915. //
  916. // Notes: Format of the section in clmt.inf:
  917. // <service name to be stopped>, <action>
  918. //
  919. //-----------------------------------------------------------------------
  920. HRESULT AnalyzeServicesStatus(
  921. HINF hInf, // Handle to Migration INF
  922. LPCTSTR lpInfSection // Section to be read from INF
  923. )
  924. {
  925. HRESULT hr = S_OK;
  926. BOOL bRet = TRUE;
  927. LONG lLineCount;
  928. LONG lLineIndex;
  929. INFCONTEXT context;
  930. TCHAR szServiceName[128];
  931. TCHAR szControl[8];
  932. TCHAR szCleanupControl[8];
  933. INT iRunningStatus;
  934. INT iServiceControl;
  935. DWORD dwCleanupControl;
  936. SC_HANDLE schService;
  937. SC_HANDLE schSCManager;
  938. SERVICE_STATUS ssStatus;
  939. if (hInf == INVALID_HANDLE_VALUE || lpInfSection == NULL)
  940. {
  941. return E_INVALIDARG;
  942. }
  943. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  944. if (schSCManager != NULL)
  945. {
  946. // Read the list of services to be reset from INF
  947. lLineCount = SetupGetLineCount(hInf, lpInfSection);
  948. for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
  949. {
  950. bRet = SetupGetLineByIndex(hInf,
  951. lpInfSection,
  952. (DWORD) lLineIndex,
  953. &context);
  954. if (bRet)
  955. {
  956. bRet = SetupGetStringField(&context,
  957. 1,
  958. szServiceName,
  959. ARRAYSIZE(szServiceName),
  960. NULL)
  961. && SetupGetIntField(&context,
  962. 2,
  963. &iRunningStatus)
  964. && SetupGetIntField(&context,
  965. 3,
  966. &iServiceControl);
  967. if (bRet)
  968. {
  969. schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
  970. if (schService != NULL)
  971. {
  972. QueryServiceStatus(schService, &ssStatus);
  973. if (ssStatus.dwCurrentState == (DWORD) iRunningStatus)
  974. {
  975. switch (iServiceControl)
  976. {
  977. case SERVICE_CONTROL_STOP:
  978. dwCleanupControl = 0; // 0 means start the service
  979. break;
  980. case SERVICE_CONTROL_PAUSE:
  981. dwCleanupControl = SERVICE_CONTROL_CONTINUE;
  982. break;
  983. }
  984. _itot(iServiceControl, szControl, 10);
  985. _ultot(dwCleanupControl, szCleanupControl, 10);
  986. WritePrivateProfileString(TEXT_SERVICE_STATUS_SECTION,
  987. szServiceName,
  988. szControl,
  989. g_szToDoINFFileName);
  990. WritePrivateProfileString(TEXT_SERVICE_STATUS_CLEANUP_SECTION,
  991. szServiceName,
  992. szCleanupControl,
  993. g_szToDoINFFileName);
  994. }
  995. CloseServiceHandle(schService);
  996. }
  997. }
  998. }
  999. }
  1000. CloseServiceHandle(schSCManager);
  1001. }
  1002. else
  1003. {
  1004. bRet = FALSE;
  1005. }
  1006. hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  1007. return hr;
  1008. }
  1009. //-----------------------------------------------------------------------
  1010. //
  1011. // Function: AnalyzeServicesStartUp
  1012. //
  1013. // Descrip: Analyze services startup type. Some components in the system
  1014. // need to be stopped and not to start automatically until
  1015. // upgraded to .NET server. So, we might need to change those
  1016. // services to "Manually Start".
  1017. // Change the Service Start Type, there are following type availabe now
  1018. // SERVICE_AUTO_START
  1019. // SERVICE_BOOT_START
  1020. // SERVICE_DEMAND_START
  1021. // SERVICE_DISABLED
  1022. // SERVICE_SYSTEM_START
  1023. //
  1024. // Returns: S_OK if function succeeded.
  1025. // else if error occured
  1026. //
  1027. // Notes: none
  1028. //
  1029. // History: 09/07/2002 rerkboos created
  1030. //
  1031. // Notes: Format of the section in clmt.inf:
  1032. // <service name>, <current start type in system>, <new start type>
  1033. //
  1034. //-----------------------------------------------------------------------
  1035. HRESULT AnalyzeServicesStartUp(
  1036. HINF hInf,
  1037. LPCTSTR lpInfSection
  1038. )
  1039. {
  1040. HRESULT hr = S_OK;
  1041. BOOL bRet = TRUE;
  1042. LONG lLineCount;
  1043. LONG lLineIndex;
  1044. INFCONTEXT context;
  1045. WCHAR szServiceName[64];
  1046. WCHAR szCurrentStartupType[8];
  1047. WCHAR szNewStartupType[8];
  1048. INT iCurrentStartupType;
  1049. INT iNewStartupType;
  1050. DWORD dwBytesNeeded;
  1051. SC_HANDLE schService;
  1052. SC_HANDLE schSCManager;
  1053. SERVICE_STATUS ssStatus;
  1054. LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
  1055. if (hInf == INVALID_HANDLE_VALUE)
  1056. {
  1057. return E_INVALIDARG;
  1058. }
  1059. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  1060. if (schSCManager != NULL)
  1061. {
  1062. lLineCount = SetupGetLineCount(hInf, lpInfSection);
  1063. for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
  1064. {
  1065. bRet = SetupGetLineByIndex(hInf,
  1066. lpInfSection,
  1067. (DWORD) lLineIndex,
  1068. &context);
  1069. if (bRet)
  1070. {
  1071. bRet = SetupGetStringField(&context,
  1072. 1,
  1073. szServiceName,
  1074. ARRAYSIZE(szServiceName),
  1075. NULL)
  1076. && SetupGetIntField(&context,
  1077. 2,
  1078. &iCurrentStartupType)
  1079. && SetupGetIntField(&context,
  1080. 3,
  1081. &iNewStartupType);
  1082. if (bRet)
  1083. {
  1084. schService = OpenService(schSCManager, szServiceName, SERVICE_QUERY_CONFIG);
  1085. if (schService != NULL)
  1086. {
  1087. lpqscBuf = (LPQUERY_SERVICE_CONFIG) MEMALLOC(4096);
  1088. if (lpqscBuf != NULL)
  1089. {
  1090. bRet = QueryServiceConfig(schService,
  1091. lpqscBuf,
  1092. 4096,
  1093. &dwBytesNeeded);
  1094. if (bRet)
  1095. {
  1096. if (lpqscBuf->dwStartType == (DWORD) iCurrentStartupType)
  1097. {
  1098. _itot(iCurrentStartupType, szCurrentStartupType, 10);
  1099. _itot(iNewStartupType, szNewStartupType, 10);
  1100. WritePrivateProfileString(TEXT_SERVICE_STARTUP_SECTION,
  1101. szServiceName,
  1102. szNewStartupType,
  1103. g_szToDoINFFileName);
  1104. WritePrivateProfileString(TEXT_SERVICE_STARTUP_CLEANUP_SECTION,
  1105. szServiceName,
  1106. szCurrentStartupType,
  1107. g_szToDoINFFileName);
  1108. }
  1109. }
  1110. MEMFREE(lpqscBuf);
  1111. }
  1112. else
  1113. {
  1114. SetLastError(ERROR_OUTOFMEMORY);
  1115. }
  1116. CloseServiceHandle(schService);
  1117. }
  1118. }
  1119. }
  1120. }
  1121. CloseServiceHandle(schSCManager);
  1122. }
  1123. else
  1124. {
  1125. bRet = FALSE;
  1126. }
  1127. hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  1128. return hr;
  1129. }
  1130. //-----------------------------------------------------------------------
  1131. //
  1132. // Function: ResetServicesStatus
  1133. //
  1134. // Descrip: Reset the services listed in specified section of INF
  1135. //
  1136. // Returns: S_OK if function succeeded.
  1137. // else if error occured
  1138. //
  1139. // Notes: none
  1140. //
  1141. // History: 04/30/2002 rerkboos created
  1142. // 07/08/2002 rerkboos modified
  1143. //
  1144. // Notes: Format of the section in clmt.inf:
  1145. // <service name to be stopped>, <action>
  1146. //
  1147. //-----------------------------------------------------------------------
  1148. HRESULT ResetServicesStatus(
  1149. HINF hInf, // Handle to INF
  1150. LPCTSTR lpInfSection // Section to be read from INF
  1151. )
  1152. {
  1153. HRESULT hr = S_OK;
  1154. BOOL bRet = TRUE;
  1155. LONG lLineCount;
  1156. LONG lLineIndex;
  1157. INFCONTEXT context;
  1158. WCHAR szServiceName[128];
  1159. INT iServiceControl;
  1160. if (hInf == INVALID_HANDLE_VALUE || lpInfSection == NULL)
  1161. {
  1162. return E_INVALIDARG;
  1163. }
  1164. // Read the list of services to be reset from INF
  1165. lLineCount = SetupGetLineCount(hInf, lpInfSection);
  1166. for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
  1167. {
  1168. bRet = SetupGetLineByIndex(hInf,
  1169. lpInfSection,
  1170. (DWORD) lLineIndex,
  1171. &context);
  1172. if (bRet)
  1173. {
  1174. bRet = SetupGetStringField(&context,
  1175. 0,
  1176. szServiceName,
  1177. ARRAYSIZE(szServiceName),
  1178. NULL)
  1179. && SetupGetIntField(&context,
  1180. 1,
  1181. &iServiceControl);
  1182. if (bRet)
  1183. {
  1184. hr = ResetServiceStatus(szServiceName,
  1185. (DWORD) iServiceControl,
  1186. 10);
  1187. }
  1188. }
  1189. }
  1190. hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  1191. return hr;
  1192. }
  1193. //-----------------------------------------------------------------------
  1194. //
  1195. // Function: ResetServicesStartUp
  1196. //
  1197. // Descrip: Reconfigure services start type. Some components in the system
  1198. // need to be stopped and not to start automatically until
  1199. // upgraded to .NET server. So, we might need to change those
  1200. // services to "Manually Start".
  1201. // Change the Service Start Type, there are following type availabe now
  1202. // SERVICE_AUTO_START
  1203. // SERVICE_BOOT_START
  1204. // SERVICE_DEMAND_START
  1205. // SERVICE_DISABLED
  1206. // SERVICE_SYSTEM_START
  1207. //
  1208. // Returns: S_OK if function succeeded.
  1209. // else if error occured
  1210. //
  1211. // Notes: none
  1212. //
  1213. // History: 04/30/2002 rerkboos created
  1214. //
  1215. // Notes: Format of the section in clmt.inf:
  1216. // <service name>, <current start type in system>, <new start type>
  1217. //
  1218. //-----------------------------------------------------------------------
  1219. HRESULT ResetServicesStartUp(
  1220. HINF hInf,
  1221. LPCTSTR lpInfSection
  1222. )
  1223. {
  1224. HRESULT hr = S_OK;
  1225. BOOL bRet = TRUE;
  1226. LONG lLineCount;
  1227. LONG lLineIndex;
  1228. INFCONTEXT context;
  1229. WCHAR szServiceName[64];
  1230. INT iNewStartupType;
  1231. if (hInf == INVALID_HANDLE_VALUE)
  1232. {
  1233. return E_INVALIDARG;
  1234. }
  1235. lLineCount = SetupGetLineCount(hInf, lpInfSection);
  1236. for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
  1237. {
  1238. bRet = SetupGetLineByIndex(hInf,
  1239. lpInfSection,
  1240. (DWORD) lLineIndex,
  1241. &context);
  1242. if (bRet)
  1243. {
  1244. bRet = SetupGetStringField(&context,
  1245. 0,
  1246. szServiceName,
  1247. ARRAYSIZE(szServiceName),
  1248. NULL)
  1249. && SetupGetIntField(&context,
  1250. 1,
  1251. &iNewStartupType);
  1252. if (bRet)
  1253. {
  1254. hr = ChangeServiceStartupType(szServiceName,
  1255. iNewStartupType,
  1256. 10);
  1257. }
  1258. }
  1259. }
  1260. hr = (bRet == TRUE ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  1261. return hr;
  1262. }
  1263. HRESULT ChangeServiceStartupType(
  1264. LPCTSTR lpServiceName,
  1265. DWORD dwNewStartupType,
  1266. DWORD dwMaxWait
  1267. )
  1268. {
  1269. SC_LOCK sclLock = NULL;
  1270. SERVICE_DESCRIPTION sdBuf;
  1271. DWORD dwBytesNeeded;
  1272. DWORD dwStartType;
  1273. SC_HANDLE schSCManager = NULL;
  1274. SC_HANDLE schService = NULL;
  1275. DWORD dwErr = ERROR_SUCCESS;
  1276. HRESULT hr = S_OK;
  1277. DWORD dwCnt;
  1278. BOOL bRet;
  1279. if (lpServiceName == NULL)
  1280. {
  1281. return E_INVALIDARG;
  1282. }
  1283. schSCManager = OpenSCManager(NULL, // machine (NULL == local)
  1284. NULL, // database (NULL == default)
  1285. SC_MANAGER_ALL_ACCESS);
  1286. if (!schSCManager)
  1287. {
  1288. dwErr = GetLastError();
  1289. goto cleanup;
  1290. }
  1291. // Need to acquire database lock before reconfiguring.
  1292. for(dwCnt = 0 ; dwCnt < dwMaxWait ; dwCnt++)
  1293. {
  1294. sclLock = LockServiceDatabase(schSCManager);
  1295. if (sclLock == NULL)
  1296. {
  1297. // Exit if the database is not locked by another process.
  1298. dwErr = GetLastError();
  1299. if (dwErr != ERROR_SERVICE_DATABASE_LOCKED)
  1300. {
  1301. goto cleanup;
  1302. }
  1303. else
  1304. {
  1305. Sleep(1000);
  1306. }
  1307. }
  1308. else
  1309. {
  1310. break;
  1311. }
  1312. }
  1313. if (sclLock != NULL)
  1314. {
  1315. // The database is locked, so it is safe to make changes.
  1316. // Open a handle to the service.
  1317. schService = OpenService(schSCManager, // SCManager database
  1318. lpServiceName, // name of service
  1319. SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG );
  1320. if (schService != NULL)
  1321. {
  1322. // Make the changes
  1323. bRet = ChangeServiceConfig(schService, // handle of service
  1324. SERVICE_NO_CHANGE, // service type: no change
  1325. dwNewStartupType, // change service start type
  1326. SERVICE_NO_CHANGE, // error control: no change
  1327. NULL, // binary path: no change
  1328. NULL, // load order group: no change
  1329. NULL, // tag ID: no change
  1330. NULL, // dependencies: no change
  1331. NULL, // account name: no change
  1332. NULL, // password: no change
  1333. NULL); // display name: no change
  1334. if (!bRet)
  1335. {
  1336. dwErr = GetLastError();
  1337. }
  1338. CloseServiceHandle(schService);
  1339. }
  1340. else
  1341. {
  1342. dwErr = GetLastError();
  1343. }
  1344. UnlockServiceDatabase(sclLock);
  1345. }
  1346. hr = S_OK;
  1347. cleanup:
  1348. if (dwErr != ERROR_SUCCESS)
  1349. {
  1350. hr = HRESULT_FROM_WIN32(dwErr);
  1351. }
  1352. if (schSCManager)
  1353. {
  1354. CloseServiceHandle(schSCManager);
  1355. }
  1356. return hr;
  1357. }
  1358. BOOL LnkFileUpdate(LPTSTR lpszFile)
  1359. {
  1360. HRESULT hr ;
  1361. hr = AddNeedUpdateLnkFile(lpszFile,&g_StrReplaceTable );
  1362. if (SUCCEEDED(hr))
  1363. {
  1364. return TRUE;
  1365. }
  1366. else
  1367. {
  1368. return FALSE;
  1369. }
  1370. }
  1371. BOOL SecTempUpdate(LPTSTR lpszFile)
  1372. {
  1373. HRESULT hr ;
  1374. hr = UpdateSecurityTemplates(lpszFile,&g_StrReplaceTable );
  1375. if (SUCCEEDED(hr))
  1376. {
  1377. return TRUE;
  1378. }
  1379. else
  1380. {
  1381. return FALSE;
  1382. }
  1383. }
  1384. //-----------------------------------------------------------------------
  1385. //
  1386. // Function: ResetServiceStatus
  1387. //
  1388. // Descrip: Reset the running (start/pause/stop) status of
  1389. // the specified service
  1390. //
  1391. // Returns: S_OK if function succeeded.
  1392. // else if error occured
  1393. //
  1394. // Notes: none
  1395. //
  1396. // History: 07/09/2002 rerkboos created
  1397. //
  1398. // Notes: Format of the section in clmt.inf:
  1399. // <service name>, <control>
  1400. //
  1401. //-----------------------------------------------------------------------
  1402. HRESULT ResetServiceStatus(
  1403. LPCTSTR lpServiceName, // Service name
  1404. DWORD dwControl, // Control for the specified service
  1405. DWORD dwMaxWait // Timeout in seconds
  1406. )
  1407. {
  1408. HRESULT hr = E_FAIL;
  1409. BOOL bRet = FALSE;
  1410. SC_HANDLE schService;
  1411. SC_HANDLE schSCManager;
  1412. SERVICE_STATUS ssStatus;
  1413. DWORD dwSec;
  1414. DWORD dwFinalStatus;
  1415. switch (dwControl)
  1416. {
  1417. case SERVICE_CONTROL_CONTINUE:
  1418. dwFinalStatus = SERVICE_RUNNING;
  1419. break;
  1420. case SERVICE_CONTROL_PAUSE:
  1421. dwFinalStatus = SERVICE_PAUSED;
  1422. break;
  1423. case SERVICE_CONTROL_STOP:
  1424. dwFinalStatus = SERVICE_STOPPED;
  1425. break;
  1426. case 0: // Start service
  1427. dwFinalStatus = SERVICE_RUNNING;
  1428. break;
  1429. }
  1430. schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  1431. if (schSCManager != NULL)
  1432. {
  1433. schService = OpenService(schSCManager, lpServiceName, SERVICE_ALL_ACCESS);
  1434. if (schService != NULL)
  1435. {
  1436. if (dwControl == 0)
  1437. {
  1438. // Start service
  1439. bRet = StartService(schService, 0, NULL);
  1440. }
  1441. else
  1442. {
  1443. // Continue, Pause, Stop service
  1444. bRet = ControlService(schService, dwControl, &ssStatus);
  1445. }
  1446. if (bRet)
  1447. {
  1448. dwSec = 0;
  1449. hr = S_FALSE;
  1450. while (QueryServiceStatus(schService, &ssStatus)
  1451. && dwSec < dwMaxWait)
  1452. {
  1453. if (ssStatus.dwCurrentState != dwFinalStatus)
  1454. {
  1455. Sleep(1000);
  1456. dwSec++;
  1457. }
  1458. else
  1459. {
  1460. hr = S_OK;
  1461. break;
  1462. }
  1463. }
  1464. if (hr != S_OK)
  1465. {
  1466. DPF(APPwar,
  1467. TEXT(" Warning! - [%s] service status cannot change from %d to %d\n"),
  1468. lpServiceName,
  1469. ssStatus.dwCurrentState,
  1470. dwFinalStatus);
  1471. }
  1472. }
  1473. CloseServiceHandle(schService);
  1474. }
  1475. CloseServiceHandle(schSCManager);
  1476. }
  1477. if (FAILED(hr))
  1478. {
  1479. hr = HRESULT_FROM_WIN32(GetLastError());
  1480. }
  1481. return hr;
  1482. }
  1483. HRESULT FinalUpdateRegForUser(HKEY hKeyUser,
  1484. LPTSTR UserName,
  1485. LPTSTR DomainName,
  1486. LPTSTR UserSid)
  1487. {
  1488. RegUpdate(g_hInfDoItem, hKeyUser, UserSid);
  1489. return S_OK;
  1490. }
  1491. /*++
  1492. Routine Description:
  1493. This routine does the per user registry search and replace, the string replace table
  1494. is in global variable g_StrReplaceTable
  1495. Arguments:
  1496. hKeyUser - user registry key handle
  1497. UserName - user name that hKeyUser belongs to
  1498. DomainName - domain name the UserName belongs to
  1499. Return Value:
  1500. NULL
  1501. --*/
  1502. HRESULT UpdateRegPerUser (HKEY hKeyUser,
  1503. LPTSTR UserName,
  1504. LPTSTR DomainName,
  1505. LPTSTR UserSid)
  1506. {
  1507. return RegistryAnalyze(hKeyUser,UserName,UserSid,&g_StrReplaceTable,NULL,0,NULL,TRUE);
  1508. }
  1509. HRESULT UpdateDSObjProp(
  1510. HINF hInf,
  1511. LPTSTR lpInfSection)
  1512. {
  1513. #define DSOBJNUMOFFIELD 3
  1514. DWORD dwFileValid[DSOBJNUMOFFIELD] = {1,1,1};
  1515. DWORD arrSizeNeeded[DSOBJNUMOFFIELD];
  1516. LPTSTR lpField[DSOBJNUMOFFIELD];
  1517. UINT LineCount,LineNo;
  1518. INFCONTEXT InfContext;
  1519. HRESULT hr;
  1520. int i;
  1521. for ( i = 0; i < DSOBJNUMOFFIELD; i++)
  1522. {
  1523. lpField[i] = NULL;
  1524. }
  1525. hr = GetMaxLenEachField(hInf,lpInfSection,FALSE,DSOBJNUMOFFIELD,DSOBJNUMOFFIELD,
  1526. (PDWORD)dwFileValid,arrSizeNeeded,FALSE);
  1527. if (hr != S_OK)
  1528. {
  1529. goto cleanup;
  1530. }
  1531. for (i = 0; i < DSOBJNUMOFFIELD; i++)
  1532. {
  1533. if (!(lpField[i] = malloc(arrSizeNeeded[i]*sizeof(TCHAR))))
  1534. {
  1535. goto cleanup;
  1536. }
  1537. }
  1538. LineCount = (UINT)SetupGetLineCount(hInf,lpInfSection);
  1539. if ((LONG)LineCount < 0)
  1540. {
  1541. hr = S_FALSE;
  1542. goto cleanup;
  1543. }
  1544. //Scan the INF file section to get the max buf required for each field
  1545. for (LineNo = 0; LineNo < LineCount; LineNo++)
  1546. {
  1547. if (!SetupGetLineByIndex(hInf,lpInfSection,LineNo,&InfContext))
  1548. {
  1549. DPF(INFwar ,TEXT("can not get line %d of section %s !"),LineNo, lpInfSection);
  1550. continue;
  1551. }
  1552. for (i = 1; i <= DSOBJNUMOFFIELD; i++)
  1553. {
  1554. SetupGetStringField(&InfContext,i,lpField[i-1],arrSizeNeeded[i-1],NULL);
  1555. }
  1556. PropertyValueHelper( lpField[0],lpField[1],NULL,lpField[2]);
  1557. }
  1558. hr =S_OK;
  1559. cleanup:
  1560. for (i = 0; i < DSOBJNUMOFFIELD; i++)
  1561. {
  1562. FreePointer(lpField[i]);
  1563. }
  1564. return hr;
  1565. }
  1566. void DoServicesAnalyze()
  1567. {
  1568. AnalyzeServicesStatus(g_hInf, TEXT_SERVICE_STATUS_SECTION);
  1569. AnalyzeServicesStartUp(g_hInf, TEXT_SERVICE_STARTUP_SECTION);
  1570. }
  1571. HRESULT INFVerifyHardLink(
  1572. HINF hInf,
  1573. LPTSTR lpszSection)
  1574. {
  1575. HRESULT hr;
  1576. INT LineCount,LineNo,nFieldIndex;
  1577. INFCONTEXT InfContext;
  1578. TCHAR szFileName[MAX_PATH+1],szExistingFileName[MAX_PATH+1],szCurrLink[MAX_PATH];
  1579. TCHAR lpszInf[MAX_PATH+1];
  1580. HINF hMyInf;
  1581. //check the INF file handle
  1582. hMyInf = hInf;
  1583. if(hMyInf == INVALID_HANDLE_VALUE)
  1584. {
  1585. hr = EnsureDoItemInfFile(lpszInf,ARRAYSIZE(lpszInf));
  1586. if (FAILED(hr))
  1587. {
  1588. goto Cleanup;
  1589. }
  1590. hMyInf = SetupOpenInfFile(lpszInf,
  1591. NULL,
  1592. INF_STYLE_WIN4,
  1593. NULL);
  1594. if (hMyInf == INVALID_HANDLE_VALUE)
  1595. {
  1596. hr = E_INVALIDARG;
  1597. goto Cleanup;
  1598. }
  1599. }
  1600. LineCount = (UINT)SetupGetLineCount(hMyInf,lpszSection);
  1601. if ((LONG)LineCount < 0)
  1602. {
  1603. hr = S_FALSE;
  1604. goto Cleanup;
  1605. }
  1606. for (LineNo = 0 ; LineNo < LineCount; LineNo++)
  1607. {
  1608. BOOL b1,b2,b3,b4;
  1609. if (!SetupGetLineByIndex(hMyInf,lpszSection,LineNo,&InfContext))
  1610. {
  1611. continue;
  1612. }
  1613. b2 = SetupGetStringField(&InfContext,2,szFileName,ARRAYSIZE(szFileName),NULL);
  1614. b3 = SetupGetStringField(&InfContext,3,szExistingFileName,ARRAYSIZE(szExistingFileName),NULL);
  1615. if (!b2 || !b3)
  1616. {
  1617. continue;
  1618. }
  1619. if (GetSymbolicLink(szFileName,szCurrLink,ARRAYSIZE(szCurrLink)))
  1620. {
  1621. if (!IsDirExisting(szCurrLink))
  1622. {
  1623. RemoveDirectory(szFileName);
  1624. }
  1625. }
  1626. }
  1627. hr = S_OK;
  1628. Cleanup:
  1629. if ( (hInf == INVALID_HANDLE_VALUE) && (hMyInf != INVALID_HANDLE_VALUE) )
  1630. {
  1631. SetupCloseInfFile(hMyInf);
  1632. }
  1633. return hr;
  1634. }