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.

1454 lines
44 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. utils2.c
  5. Abstract:
  6. utillities to update lnk/msi/... file
  7. Author:
  8. Xiaofeng Zang (xiaoz) 08-Oct-2001 Created
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #define NOT_USE_SAFE_STRING
  13. #include "clmt.h"
  14. #include <objbase.h>
  15. #include <shellapi.h>
  16. #include <shlguid.h>
  17. #include <comdef.h>
  18. #include <iads.h>
  19. #include <adsiid.h>
  20. #include <adshlp.h>
  21. #define STRSAFE_LIB
  22. #include <strsafe.h>
  23. class CServiceHandle
  24. {
  25. public :
  26. CServiceHandle() { _h = 0; }
  27. CServiceHandle( SC_HANDLE hSC ) : _h( hSC ) {}
  28. ~CServiceHandle() { Free(); }
  29. void Set( SC_HANDLE h ) { _h = h; }
  30. SC_HANDLE Get() { return _h; }
  31. BOOL IsNull() { return ( 0 == _h ); }
  32. void Free() { if ( 0 != _h ) CloseServiceHandle( _h ); _h = 0; }
  33. private:
  34. SC_HANDLE _h;
  35. };
  36. //+-------------------------------------------------------------------------
  37. //
  38. // Function: IsServiceRunning
  39. //
  40. // Synopsis: Determines if a service is running
  41. //
  42. // Arguments: pwcServiceName -- The name (short or long) of the service
  43. //
  44. // Returns: TRUE if the service is running, FALSE otherwise or if the
  45. // system is low on resources or the status can't be queried.
  46. //
  47. // History: 3/22/2002 geoffguo Created
  48. //
  49. //--------------------------------------------------------------------------
  50. BOOL IsServiceRunning(LPCTSTR pwcServiceName)
  51. {
  52. CServiceHandle xhSC( OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS ) );
  53. if ( xhSC.IsNull() )
  54. return FALSE;
  55. CServiceHandle xhService( OpenService( xhSC.Get(),
  56. pwcServiceName,
  57. SERVICE_QUERY_STATUS ) );
  58. if ( xhSC.IsNull() )
  59. return FALSE;
  60. SERVICE_STATUS svcStatus;
  61. if ( QueryServiceStatus( xhService.Get(), &svcStatus ) )
  62. return ( SERVICE_RUNNING == svcStatus.dwCurrentState );
  63. return FALSE;
  64. }
  65. HRESULT AddNeedUpdateLnkFile(
  66. LPTSTR pszShortcutFile,
  67. PREG_STRING_REPLACE lpStrList)
  68. {
  69. HRESULT hr;
  70. IShellLink *psl = NULL;
  71. TCHAR szGotPath [MAX_PATH];
  72. TCHAR szNewPath [2*MAX_PATH];
  73. TCHAR szArg[INFOTIPSIZE+1],szNewArg[2*INFOTIPSIZE+1];
  74. WIN32_FIND_DATA wfd;
  75. IPersistFile *ppf = NULL;
  76. int nIcon;
  77. LPTSTR lpszOneline = NULL;
  78. size_t cchOneline = 0;
  79. TCHAR szIndex[MAX_PATH];
  80. LPTSTR lpszAppend = TEXT("");
  81. BOOL bLnkUpdated = FALSE;
  82. BOOL bTargetGot = FALSE;
  83. BOOL bTargetUpdated = FALSE;
  84. DWORD dwAttrib;
  85. LPTSTR lpszStrWithExtraQuote;
  86. if (!pszShortcutFile || !pszShortcutFile[0] || !lpStrList)
  87. {
  88. hr = S_FALSE;
  89. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: InValid Parameter(s)"));
  90. goto Cleanup;
  91. }
  92. //Allocate memory for "LnkFile,TargetPath,IconPath,Working Dir,Relative Path and Argument"
  93. cchOneline = lstrlen(pszShortcutFile) + 5 * MAX_PATH + INFOTIPSIZE+1;
  94. if (!(lpszOneline = (LPTSTR)malloc(cchOneline * sizeof(TCHAR))))
  95. {
  96. hr = E_OUTOFMEMORY;
  97. goto Cleanup;
  98. }
  99. // Get a pointer to the IShellLink interface.
  100. hr = CoCreateInstance (CLSID_ShellLink,
  101. NULL,
  102. CLSCTX_INPROC_SERVER,
  103. IID_IShellLink,
  104. (void **)&psl);
  105. if (FAILED (hr))
  106. {
  107. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: CoCreateInstance CLSID_ShellLink return %d (%#x)\n"), hr, hr);
  108. goto Cleanup;
  109. }
  110. // Get a pointer to the IPersistFile interface.
  111. hr = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
  112. if (FAILED(hr))
  113. {
  114. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: QueryInterface IID_IPersistFile return %d (%#x)\n"), hr, hr);
  115. goto Cleanup;
  116. }
  117. // Load the shortcut.
  118. hr = ppf->Load (pszShortcutFile, STGM_READWRITE );
  119. if (FAILED(hr))
  120. {
  121. hr = S_FALSE;
  122. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: can not load shortcut file %s"),pszShortcutFile);
  123. goto Cleanup;
  124. }
  125. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("\"%s\""),pszShortcutFile);
  126. if (FAILED(hr))
  127. {
  128. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer lpszOneline is too small for %s"),pszShortcutFile);
  129. goto Cleanup;
  130. }
  131. // Get the path to the shortcut target.
  132. hr = psl->GetPath (szGotPath,
  133. ARRAYSIZE(szGotPath),
  134. (WIN32_FIND_DATA *)&wfd,
  135. SLGP_RAWPATH);
  136. if (SUCCEEDED (hr))
  137. { //Succeeded get the target
  138. DWORD dwNum ;
  139. DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetPath %s OK "), szGotPath);
  140. //Set bTargetGot so that it cab be used to set relative target path
  141. bTargetGot = TRUE;
  142. //szGotPath contains LNK's target path, if dwNum >0 , it means szGotPath
  143. //contains (localized) path that we renamed
  144. dwNum = GetMaxMatchNum(szGotPath,lpStrList);
  145. //call ReplaceMultiMatchInString ,to replace szGotPath's localized folder
  146. //with english one, and put new path in szNewPath
  147. if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
  148. {
  149. lpszAppend = szNewPath;
  150. bTargetUpdated = TRUE;
  151. bLnkUpdated = TRUE;
  152. }
  153. }
  154. else
  155. {
  156. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetPath %s Error = %d"), szGotPath,hr);
  157. }
  158. if (MyStrCmpI(lpszAppend,TEXT("")))
  159. {
  160. hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
  161. if (SUCCEEDED(hr))
  162. {
  163. if (lpszStrWithExtraQuote)
  164. {
  165. lpszAppend = lpszStrWithExtraQuote;
  166. }
  167. }
  168. }
  169. else
  170. {
  171. lpszStrWithExtraQuote = NULL;
  172. }
  173. //Append the new quoted target path to lpszOneline
  174. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
  175. FreePointer(lpszStrWithExtraQuote);
  176. //check StringCchPrintf here, because we want to free lpszStrWithExtraQuote before
  177. //we do a jump (if necessary)
  178. if (FAILED(hr))
  179. {
  180. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer lpszOneline is too small for %s"),lpszAppend);
  181. goto Cleanup;
  182. }
  183. //if we arrive here , we have succeeded in appeneding target to the lszOneline
  184. //we will update relative target path ,which is relative to where the current
  185. //lnk resides
  186. lpszAppend = TEXT("");
  187. if (bTargetGot) //this means we succeeded get the target path
  188. {
  189. DWORD dwNum ;
  190. //szNewLnkFilePath is the lnk full path with localized folder renamed to english one(if any)
  191. TCHAR szNewLnkFilePath[2*MAX_PATH],szCurrTarget[2*MAX_PATH];
  192. TCHAR szExpandedCurrTarget[2*MAX_PATH];
  193. TCHAR szNewTarget[2*MAX_PATH];
  194. //Check to see whether current pszShortcutFile resides a direcory that contains
  195. //localized folder we renamed
  196. dwNum = GetMaxMatchNum(pszShortcutFile,lpStrList);
  197. if (dwNum)
  198. {
  199. if (!ReplaceMultiMatchInString(pszShortcutFile,szNewLnkFilePath,
  200. ARRAYSIZE(szNewLnkFilePath),dwNum,lpStrList, &dwAttrib, TRUE))
  201. {
  202. //szNewLnkFilePath now is full path with localized folder renamed to english one
  203. //if we fail do ReplaceMultiMatchInString, just clone to szNewLnkFilePath
  204. hr = StringCchCopy(szNewLnkFilePath,ARRAYSIZE(szNewLnkFilePath),pszShortcutFile);
  205. if (FAILED(hr))
  206. {
  207. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewLnkFilePath is too small for %s"),pszShortcutFile);
  208. goto Cleanup;
  209. }
  210. }
  211. }
  212. else
  213. {
  214. //If pszShortcutFile does not contains any localized folder we renamed,
  215. //just clone to szNewLnkFilePath
  216. hr = StringCchCopy(szNewLnkFilePath,ARRAYSIZE(szNewLnkFilePath),pszShortcutFile);
  217. if (FAILED(hr))
  218. {
  219. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewLnkFilePath is too small for %s"),pszShortcutFile);
  220. goto Cleanup;
  221. }
  222. }
  223. if (bTargetUpdated)
  224. {
  225. if (FAILED(hr = StringCchCopy(szCurrTarget,ARRAYSIZE(szCurrTarget),szNewPath)))
  226. {
  227. goto Cleanup;
  228. }
  229. }
  230. else
  231. {
  232. if (FAILED(hr = StringCchCopy(szCurrTarget,ARRAYSIZE(szCurrTarget),szGotPath)))
  233. {
  234. goto Cleanup;
  235. }
  236. }
  237. //target may contains enviroment variable
  238. if (!ExpandEnvironmentStrings(szCurrTarget,szExpandedCurrTarget,ARRAYSIZE(szExpandedCurrTarget)))
  239. {
  240. hr = HRESULT_FROM_WIN32(GetLastError());
  241. goto Cleanup;
  242. }
  243. //Check whether target contains the folder we renamed
  244. dwNum = GetMaxMatchNum(szExpandedCurrTarget,lpStrList);
  245. if (dwNum)
  246. {
  247. if (!ReplaceMultiMatchInString(szExpandedCurrTarget,szNewTarget,ARRAYSIZE(szNewTarget),dwNum,lpStrList, &dwAttrib, TRUE))
  248. {
  249. hr = StringCchCopy(szNewTarget,ARRAYSIZE(szNewTarget),szExpandedCurrTarget);
  250. if (FAILED(hr))
  251. {
  252. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewTarget is too small for %s"),szExpandedCurrTarget);
  253. goto Cleanup;
  254. }
  255. }
  256. }
  257. else
  258. {
  259. hr = StringCchCopy(szNewTarget,ARRAYSIZE(szNewTarget),szExpandedCurrTarget);
  260. if (FAILED(hr))
  261. {
  262. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: buffer szNewTarget is too small for %s"),szExpandedCurrTarget);
  263. goto Cleanup;
  264. }
  265. }
  266. if (PathRelativePathTo(szNewPath,szNewLnkFilePath,0,szNewTarget,0))
  267. {
  268. lpszAppend = szNewPath;
  269. bLnkUpdated = TRUE;
  270. }
  271. }
  272. if (MyStrCmpI(lpszAppend,TEXT("")))
  273. {
  274. hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
  275. if (SUCCEEDED(hr))
  276. {
  277. if (lpszStrWithExtraQuote)
  278. {
  279. lpszAppend = lpszStrWithExtraQuote;
  280. }
  281. }
  282. }
  283. else
  284. {
  285. lpszStrWithExtraQuote = NULL;
  286. }
  287. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
  288. FreePointer(lpszStrWithExtraQuote);
  289. if (FAILED(hr))
  290. {
  291. goto Cleanup;
  292. }
  293. lpszAppend = TEXT("");
  294. hr = psl->GetIconLocation (szGotPath,ARRAYSIZE(szGotPath),&nIcon);
  295. if (SUCCEEDED (hr))
  296. {
  297. DWORD dwNum ;
  298. DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetIconPath %s OK "), szGotPath);
  299. dwNum = GetMaxMatchNum(szGotPath,lpStrList);
  300. if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
  301. {
  302. lpszAppend = szNewPath;
  303. bLnkUpdated = TRUE;
  304. }
  305. }
  306. else
  307. {
  308. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetIconPath %s Error = %d"), szGotPath,hr);
  309. }
  310. if (MyStrCmpI(lpszAppend,TEXT("")))
  311. {
  312. hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
  313. if (SUCCEEDED(hr))
  314. {
  315. if (lpszStrWithExtraQuote)
  316. {
  317. lpszAppend = lpszStrWithExtraQuote;
  318. }
  319. }
  320. }
  321. else
  322. {
  323. lpszStrWithExtraQuote = NULL;
  324. }
  325. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
  326. FreePointer(lpszStrWithExtraQuote);
  327. if (FAILED(hr))
  328. {
  329. goto Cleanup;
  330. }
  331. lpszAppend = TEXT("");
  332. hr = psl->GetWorkingDirectory (szGotPath,ARRAYSIZE(szGotPath));
  333. if (SUCCEEDED (hr))
  334. {
  335. DWORD dwNum ;
  336. DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetWorkingDirPath %s OK "), szGotPath);
  337. dwNum = GetMaxMatchNum(szGotPath,lpStrList);
  338. if (dwNum && ReplaceMultiMatchInString(szGotPath,szNewPath,ARRAYSIZE(szNewPath),dwNum,lpStrList, &dwAttrib, TRUE))
  339. {
  340. bLnkUpdated = TRUE;
  341. lpszAppend = szNewPath;
  342. }
  343. }
  344. else
  345. {
  346. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetWorkingDirPath %s Error = %d"), szGotPath,hr);
  347. }
  348. if (MyStrCmpI(lpszAppend,TEXT("")))
  349. {
  350. hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
  351. if (SUCCEEDED(hr))
  352. {
  353. if (lpszStrWithExtraQuote)
  354. {
  355. lpszAppend = lpszStrWithExtraQuote;
  356. }
  357. }
  358. }
  359. else
  360. {
  361. lpszStrWithExtraQuote = NULL;
  362. }
  363. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
  364. FreePointer(lpszStrWithExtraQuote);
  365. if (FAILED(hr))
  366. {
  367. goto Cleanup;
  368. }
  369. lpszAppend = TEXT("");
  370. hr = psl->GetArguments (szArg,ARRAYSIZE(szArg));
  371. if (SUCCEEDED (hr))
  372. {
  373. DWORD dwNum ;
  374. DPF (INFinf,TEXT("AddNeedUpdateLnkFile: GetArguments %s OK "), szArg);
  375. dwNum = GetMaxMatchNum(szArg,lpStrList);
  376. if (dwNum && ReplaceMultiMatchInString(szArg,szNewArg,ARRAYSIZE(szNewArg),dwNum,lpStrList, &dwAttrib, TRUE))
  377. {
  378. bLnkUpdated = TRUE;
  379. lpszAppend = szNewArg;
  380. }
  381. }
  382. else
  383. {
  384. DPF (INFwar,TEXT("AddNeedUpdateLnkFile: GetArguments %s Error = %d"), pszShortcutFile,hr);
  385. }
  386. if (MyStrCmpI(lpszAppend,TEXT("")))
  387. {
  388. hr = AddExtraQuoteEtc(lpszAppend,&lpszStrWithExtraQuote);
  389. if (SUCCEEDED(hr))
  390. {
  391. if (lpszStrWithExtraQuote)
  392. {
  393. lpszAppend = lpszStrWithExtraQuote;
  394. }
  395. }
  396. }
  397. else
  398. {
  399. lpszStrWithExtraQuote = NULL;
  400. }
  401. hr = StringCchPrintf(lpszOneline,cchOneline,TEXT("%s,\"%s\""),lpszOneline,lpszAppend);
  402. FreePointer(lpszStrWithExtraQuote);
  403. if (FAILED(hr))
  404. {
  405. goto Cleanup;
  406. }
  407. if (bLnkUpdated)
  408. {
  409. g_dwKeyIndex++;
  410. _itot(g_dwKeyIndex,szIndex,16);
  411. if (!WritePrivateProfileString(TEXT("LNK"),szIndex,lpszOneline,g_szToDoINFFileName))
  412. {
  413. hr = HRESULT_FROM_WIN32(GetLastError());
  414. }
  415. else
  416. {
  417. hr = S_OK;
  418. }
  419. }
  420. else
  421. {
  422. hr = S_OK;
  423. }
  424. Cleanup:
  425. if (psl)
  426. {
  427. psl->Release ();
  428. }
  429. if (ppf)
  430. {
  431. ppf->Release ();
  432. }
  433. FreePointer(lpszOneline);
  434. return hr;
  435. }
  436. HRESULT BatchFixPathInLink(
  437. HINF hInf,
  438. LPTSTR lpszSection)
  439. {
  440. HRESULT hr;
  441. IShellLink *psl = NULL;
  442. WIN32_FIND_DATA wfd;
  443. IPersistFile *ppf = NULL;
  444. int nIcon;
  445. BOOL bSucceedOnce = FALSE;
  446. UINT LineCount,LineNo;
  447. INFCONTEXT InfContext;
  448. LPTSTR lpszLnkFile = NULL,lpszPath = NULL,lpszIcon = NULL,lpszWorkingDir = NULL,
  449. lpszRelPath = NULL,lpszArg = NULL;
  450. DWORD cchMaxLnkFile = 0,cchMaxPath = 0,cchMaxIcon = 0,cchMaxWorkingDir = 0,
  451. cchMaxRelPath = 0,cchMaxArg = 0;
  452. DWORD dwFileAttrib;
  453. BOOL bFileAttribChanged ;
  454. if ((hInf == INVALID_HANDLE_VALUE) || !lpszSection)
  455. {
  456. hr = E_INVALIDARG;
  457. goto Cleanup;
  458. }
  459. LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
  460. if ((LONG)LineCount <= 0)
  461. {
  462. hr = S_FALSE;
  463. DPF(INFwar ,TEXT("section name %s is empty failed !"),lpszSection);
  464. goto Cleanup;
  465. }
  466. for(LineNo=0; LineNo<LineCount; LineNo++)
  467. {
  468. DWORD cchTmpLnkFile = 0,cchTmpPath = 0,cchTmpIcon = 0,cchTmpWorkingDir = 0,
  469. cchTmpRelPath = 0,cchTmpArg = 0;
  470. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  471. {
  472. DPF(INFerr ,TEXT("can not get line %n of section %s !"),LineNo, lpszSection);
  473. hr = E_FAIL;
  474. goto Cleanup;
  475. }
  476. if (!SetupGetStringField(&InfContext,1,NULL,0,&cchTmpLnkFile))
  477. {
  478. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 1 failed !"),lpszSection, LineNo);
  479. hr = E_FAIL;
  480. goto Cleanup;
  481. }
  482. if (!SetupGetStringField(&InfContext,2,NULL,0,&cchTmpPath))
  483. {
  484. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 2 failed !"),lpszSection, LineNo);
  485. hr = E_FAIL;
  486. goto Cleanup;
  487. }
  488. if (!SetupGetStringField(&InfContext,3,NULL,0,&cchTmpRelPath))
  489. {
  490. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 3 failed !"),lpszSection, LineNo);
  491. hr = E_FAIL;
  492. goto Cleanup;
  493. }
  494. if (!SetupGetStringField(&InfContext,4,NULL,0,&cchTmpIcon))
  495. {
  496. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 4 failed !"),lpszSection, LineNo);
  497. hr = E_FAIL;
  498. goto Cleanup;
  499. }
  500. if (!SetupGetStringField(&InfContext,5,NULL,0,&cchTmpWorkingDir))
  501. {
  502. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 5 failed !"),lpszSection, LineNo);
  503. hr = E_FAIL;
  504. goto Cleanup;
  505. }
  506. if (!SetupGetStringField(&InfContext,6,NULL,0,&cchTmpArg))
  507. {
  508. DPF(INFerr ,TEXT("get [%s] 's line %d 's Field 6 failed !"),lpszSection, LineNo);
  509. hr = E_FAIL;
  510. goto Cleanup;
  511. }
  512. cchMaxLnkFile = max(cchMaxLnkFile,cchTmpLnkFile);
  513. cchMaxPath = max(cchMaxPath,cchTmpPath);
  514. cchMaxIcon = max(cchMaxIcon,cchTmpIcon);
  515. cchMaxWorkingDir = max(cchMaxWorkingDir,cchTmpWorkingDir);
  516. cchMaxRelPath = max(cchMaxRelPath,cchTmpRelPath);
  517. cchMaxArg = max(cchMaxArg,cchTmpArg);
  518. }
  519. if (cchMaxLnkFile)
  520. {
  521. if (!(lpszLnkFile = (LPTSTR)malloc(++cchMaxLnkFile * sizeof(TCHAR))))
  522. {
  523. hr = E_OUTOFMEMORY;
  524. goto Cleanup;
  525. }
  526. }
  527. if (cchMaxPath)
  528. {
  529. if (!(lpszPath = (LPTSTR)malloc(++cchMaxPath * sizeof(TCHAR))))
  530. {
  531. hr = E_OUTOFMEMORY;
  532. goto Cleanup;
  533. }
  534. }
  535. if (cchMaxIcon)
  536. {
  537. if (!(lpszIcon = (LPTSTR)malloc(++cchMaxIcon * sizeof(TCHAR))))
  538. {
  539. hr = E_OUTOFMEMORY;
  540. goto Cleanup;
  541. }
  542. }
  543. if (cchMaxWorkingDir)
  544. {
  545. if (!(lpszWorkingDir = (LPTSTR)malloc(++cchMaxWorkingDir * sizeof(TCHAR))))
  546. {
  547. hr = E_OUTOFMEMORY;
  548. goto Cleanup;
  549. }
  550. }
  551. if (cchMaxRelPath)
  552. {
  553. if (!(lpszRelPath = (LPTSTR)malloc(++cchMaxRelPath * sizeof(TCHAR))))
  554. {
  555. hr = E_OUTOFMEMORY;
  556. goto Cleanup;
  557. }
  558. }
  559. if (cchMaxArg)
  560. {
  561. if (!(lpszArg = (LPTSTR)malloc(++cchMaxArg * sizeof(TCHAR))))
  562. {
  563. hr = E_OUTOFMEMORY;
  564. goto Cleanup;
  565. }
  566. }
  567. hr = CoCreateInstance (CLSID_ShellLink,
  568. NULL,
  569. CLSCTX_INPROC_SERVER,
  570. IID_IShellLink,
  571. (void **)&psl);
  572. if (FAILED (hr))
  573. {
  574. psl = NULL;
  575. goto Cleanup;
  576. }
  577. // Get a pointer to the IPersistFile interface.
  578. hr = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
  579. if (FAILED(hr))
  580. {
  581. ppf = NULL;
  582. goto Cleanup;
  583. }
  584. for(LineNo=0; LineNo<LineCount; LineNo++)
  585. {
  586. BOOL bSucceededOnce = FALSE;
  587. SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext);
  588. if (lpszLnkFile)
  589. {
  590. SetupGetStringField(&InfContext,1,lpszLnkFile,cchMaxLnkFile,NULL);
  591. }
  592. if (lpszPath)
  593. {
  594. SetupGetStringField(&InfContext,2,lpszPath,cchMaxPath,NULL);
  595. }
  596. if (lpszRelPath)
  597. {
  598. SetupGetStringField(&InfContext,3,lpszRelPath,cchMaxRelPath,NULL);
  599. }
  600. if (lpszIcon)
  601. {
  602. SetupGetStringField(&InfContext,4,lpszIcon,cchMaxIcon,NULL);
  603. }
  604. if (lpszWorkingDir)
  605. {
  606. SetupGetStringField(&InfContext,5,lpszWorkingDir,cchMaxWorkingDir,NULL);
  607. }
  608. if (lpszArg)
  609. {
  610. SetupGetStringField(&InfContext,6,lpszArg,cchMaxArg,NULL);
  611. }
  612. bFileAttribChanged = FALSE;
  613. dwFileAttrib = GetFileAttributes(lpszLnkFile);
  614. if (INVALID_FILE_ATTRIBUTES == dwFileAttrib)
  615. {
  616. //but put a waring log here
  617. continue;
  618. }
  619. if ( (dwFileAttrib & FILE_ATTRIBUTE_READONLY)
  620. ||(dwFileAttrib & FILE_ATTRIBUTE_SYSTEM) )
  621. {
  622. if (!SetFileAttributes(lpszLnkFile,FILE_ATTRIBUTE_NORMAL))
  623. {
  624. //but put a waring log here
  625. continue;
  626. }
  627. bFileAttribChanged = TRUE;
  628. }
  629. hr = ppf->Load (lpszLnkFile, STGM_READWRITE );
  630. if (FAILED(hr))
  631. {
  632. //but put a waring log here
  633. continue;
  634. }
  635. if (lpszPath && lpszPath[0])
  636. {
  637. hr = psl->SetPath (lpszPath);
  638. if (SUCCEEDED(hr))
  639. {
  640. bSucceededOnce = TRUE;
  641. }
  642. }
  643. if (lpszRelPath && lpszRelPath[0])
  644. {
  645. hr = psl->SetRelativePath(lpszRelPath,0);
  646. if (SUCCEEDED(hr))
  647. {
  648. bSucceededOnce = TRUE;
  649. }
  650. }
  651. if (lpszIcon && lpszIcon[0])
  652. {
  653. TCHAR szGotPath[MAX_PATH];
  654. hr = psl->GetIconLocation (szGotPath,ARRAYSIZE(szGotPath),&nIcon);
  655. if (SUCCEEDED(hr))
  656. {
  657. hr = psl->SetIconLocation (lpszIcon,nIcon);
  658. if (SUCCEEDED(hr))
  659. {
  660. bSucceededOnce = TRUE;
  661. }
  662. }
  663. }
  664. if (lpszWorkingDir && lpszWorkingDir[0])
  665. {
  666. hr = psl->SetWorkingDirectory (lpszWorkingDir);
  667. if (SUCCEEDED(hr))
  668. {
  669. bSucceededOnce = TRUE;
  670. }
  671. }
  672. if (lpszArg && lpszArg[0])
  673. {
  674. hr = psl->SetArguments (lpszArg);
  675. if (SUCCEEDED(hr))
  676. {
  677. bSucceededOnce = TRUE;
  678. }
  679. }
  680. if (bSucceededOnce)
  681. {
  682. hr = ppf->Save (lpszLnkFile,TRUE);
  683. if (! SUCCEEDED (hr))
  684. {
  685. DPF (dlError,TEXT("FixPathInLink: Save %s Error = %d"), lpszLnkFile,hr);
  686. }
  687. else
  688. {
  689. DPF (dlInfo,TEXT("FixPathInLink: Save %s OK = %d"), lpszLnkFile,hr);
  690. }
  691. }
  692. if (bFileAttribChanged)
  693. {
  694. SetFileAttributes (lpszLnkFile, dwFileAttrib);
  695. }
  696. }
  697. hr = S_OK;
  698. Cleanup:
  699. if (psl)
  700. {
  701. psl->Release ();
  702. }
  703. if (ppf)
  704. {
  705. ppf->Release ();
  706. }
  707. FreePointer(lpszPath);
  708. FreePointer(lpszIcon);
  709. FreePointer(lpszRelPath);
  710. FreePointer(lpszWorkingDir);
  711. FreePointer(lpszArg);
  712. FreePointer(lpszLnkFile);
  713. return hr;
  714. }
  715. HRESULT RenameRDN(
  716. LPTSTR lpContainerPathWithLDAP,
  717. LPTSTR lpOldFQDNWithLDAP,
  718. LPTSTR lpNewRDNWithCN
  719. )
  720. {
  721. HRESULT hr;
  722. IADsContainer *pContainer = NULL;
  723. IDispatch *pDispatch = NULL;
  724. BSTR bstrOldFQDNWithLDAP = SysAllocString(lpOldFQDNWithLDAP);
  725. BSTR bstrNewRDNWithCN = SysAllocString(lpNewRDNWithCN);
  726. if (!bstrOldFQDNWithLDAP || !bstrNewRDNWithCN )
  727. {
  728. hr = E_OUTOFMEMORY;
  729. goto Cleanup;
  730. }
  731. hr = ADsGetObject(lpContainerPathWithLDAP,
  732. IID_IADsContainer,
  733. (VOID **) &pContainer);
  734. if (SUCCEEDED(hr))
  735. {
  736. // Rename the RDN here
  737. hr = pContainer->MoveHere(bstrOldFQDNWithLDAP,
  738. bstrNewRDNWithCN,
  739. &pDispatch);
  740. if (SUCCEEDED(hr))
  741. {
  742. pDispatch->Release();
  743. }
  744. pContainer->Release();
  745. }
  746. Cleanup:
  747. if (bstrOldFQDNWithLDAP)
  748. {
  749. SysFreeString(bstrOldFQDNWithLDAP);
  750. }
  751. if (bstrNewRDNWithCN)
  752. {
  753. SysFreeString(bstrNewRDNWithCN);
  754. }
  755. return hr;
  756. }
  757. // Pass in the interface ptr to the property value
  758. // will return a BSTR value of the data.
  759. // The IADsPropertyValue::get_ADsType() is called to retrieve the
  760. // ADSTYPE valued enum
  761. // This enum is then used to determine which IADsPropertyValue method
  762. // to call to receive the actual data
  763. // CALLER assumes responsibility for freeing returned BSTR
  764. HRESULT GetIADsPropertyValueAsBSTR(BSTR * pbsRet,IADsPropertyEntry *pAdsEntry, IADsPropertyValue * pAdsPV)
  765. {
  766. HRESULT hr = S_OK;
  767. long lAdsType;
  768. hr = pAdsPV->get_ADsType(&lAdsType);
  769. if (FAILED(hr))
  770. return hr;
  771. switch (lAdsType)
  772. {
  773. case ADSTYPE_INVALID :
  774. {
  775. *pbsRet = SysAllocString(L"<ADSTYPE_INVALID>");
  776. }
  777. break;
  778. case ADSTYPE_DN_STRING :
  779. {
  780. hr = pAdsPV->get_DNString(pbsRet);
  781. }
  782. break;
  783. case ADSTYPE_CASE_EXACT_STRING :
  784. {
  785. hr = pAdsPV->get_CaseExactString(pbsRet);
  786. }
  787. break;
  788. case ADSTYPE_CASE_IGNORE_STRING :
  789. {
  790. hr = pAdsPV->get_CaseIgnoreString(pbsRet);
  791. }
  792. break;
  793. case ADSTYPE_PRINTABLE_STRING :
  794. {
  795. hr = pAdsPV->get_PrintableString(pbsRet);
  796. }
  797. break;
  798. case ADSTYPE_NUMERIC_STRING :
  799. {
  800. hr = pAdsPV->get_NumericString(pbsRet);
  801. }
  802. break;
  803. case ADSTYPE_BOOLEAN :
  804. {
  805. long b;
  806. hr = pAdsPV->get_Boolean(&b);
  807. if (SUCCEEDED(hr))
  808. {
  809. if (b)
  810. *pbsRet = SysAllocString(L"<TRUE>");
  811. else
  812. *pbsRet = SysAllocString(L"<FALSE>");
  813. }
  814. }
  815. break;
  816. case ADSTYPE_INTEGER :
  817. {
  818. long lInt;
  819. hr = pAdsPV->get_Integer(&lInt);
  820. if (SUCCEEDED(hr))
  821. {
  822. WCHAR wOut[100];
  823. hr = StringCchPrintf(wOut,ARRAYSIZE(wOut),L"%d",lInt);
  824. *pbsRet = SysAllocString(wOut);
  825. }
  826. }
  827. break;
  828. case ADSTYPE_OCTET_STRING :
  829. {
  830. *pbsRet = SysAllocString(L"<ADSTYPE_OCTET_STRING>");
  831. BSTR bsName= NULL;
  832. VARIANT vOctet;
  833. DWORD dwSLBound;
  834. DWORD dwSUBound;
  835. void HUGEP *pArray;
  836. VariantInit(&vOctet);
  837. //Get the name of the property to handle
  838. //the properties we're interested in.
  839. pAdsEntry->get_Name(&bsName);
  840. hr = pAdsPV->get_OctetString(&vOctet);
  841. //Get a pointer to the bytes in the octet string.
  842. if (SUCCEEDED(hr))
  843. {
  844. hr = SafeArrayGetLBound( V_ARRAY(&vOctet),
  845. 1,
  846. (long FAR *) &dwSLBound );
  847. hr = SafeArrayGetUBound( V_ARRAY(&vOctet),
  848. 1,
  849. (long FAR *) &dwSUBound );
  850. if (SUCCEEDED(hr))
  851. {
  852. hr = SafeArrayAccessData( V_ARRAY(&vOctet),
  853. &pArray );
  854. if (FAILED(hr))
  855. {
  856. break;
  857. }
  858. }
  859. else
  860. {
  861. break;
  862. }
  863. /* Since an Octet String has a specific meaning
  864. depending on the attribute name, handle two
  865. common ones here
  866. */
  867. if (0==wcscmp(L"objectGUID", bsName))
  868. {
  869. //LPOLESTR szDSGUID = new WCHAR [39];
  870. WCHAR szDSGUID[39];
  871. //Cast to LPGUID
  872. LPGUID pObjectGUID = (LPGUID)pArray;
  873. //Convert GUID to string.
  874. ::StringFromGUID2(*pObjectGUID, szDSGUID, 39);
  875. *pbsRet = SysAllocString(szDSGUID);
  876. }
  877. else if (0==wcscmp(L"objectSid", bsName))
  878. {
  879. PSID pObjectSID = (PSID)pArray;
  880. //Convert SID to string.
  881. LPOLESTR szSID = NULL;
  882. ConvertSidToStringSid(pObjectSID, &szSID);
  883. *pbsRet = SysAllocString(szSID);
  884. LocalFree(szSID);
  885. }
  886. else
  887. {
  888. *pbsRet = SysAllocString(L"<Value of type Octet String. No Conversion>");
  889. }
  890. SafeArrayUnaccessData( V_ARRAY(&vOctet) );
  891. VariantClear(&vOctet);
  892. }
  893. SysFreeString(bsName);
  894. }
  895. break;
  896. case ADSTYPE_LARGE_INTEGER :
  897. {
  898. *pbsRet = SysAllocString(L"<ADSTYPE_LARGE_INTEGER>");
  899. }
  900. break;
  901. case ADSTYPE_PROV_SPECIFIC :
  902. {
  903. *pbsRet = SysAllocString(L"<ADSTYPE_PROV_SPECIFIC>");
  904. }
  905. break;
  906. case ADSTYPE_OBJECT_CLASS :
  907. {
  908. hr = pAdsPV->get_CaseIgnoreString(pbsRet);
  909. }
  910. break;
  911. case ADSTYPE_PATH :
  912. {
  913. hr = pAdsPV->get_CaseIgnoreString(pbsRet);
  914. }
  915. break;
  916. case ADSTYPE_NT_SECURITY_DESCRIPTOR :
  917. {
  918. *pbsRet = SysAllocString(L"<ADSTYPE_NT_SECURITY_DESCRIPTOR>");
  919. }
  920. break;
  921. default:
  922. *pbsRet = SysAllocString(L"<UNRECOGNIZED>");
  923. break;
  924. }
  925. return hr;
  926. }
  927. HRESULT PropertyValueHelper(
  928. LPTSTR lpObjPathWithLDAP,
  929. LPTSTR lpPropName,
  930. LPTSTR *lplpValue,
  931. LPTSTR lpNewValue)
  932. {
  933. IADsPropertyList *pList = NULL;
  934. IADsPropertyEntry *pEntry = NULL;
  935. IADs *pObj = NULL;
  936. VARIANT var,varEnrty;
  937. long valType = ADSTYPE_PATH;
  938. HRESULT hr;
  939. BSTR bstrPropName = NULL;
  940. BSTR bstrNewValue = NULL;
  941. // bind to directory object
  942. hr = ADsGetObject(lpObjPathWithLDAP,
  943. IID_IADsPropertyList,
  944. (void**)&pList);
  945. if (S_OK != hr)
  946. {
  947. pList = NULL;
  948. goto exit;
  949. }
  950. // initialize the property cache
  951. hr = pList->QueryInterface(IID_IADs,(void**)&pObj);
  952. if (S_OK != hr)
  953. {
  954. pObj = NULL;
  955. goto exit;
  956. }
  957. pObj->GetInfo();
  958. // get a property entry
  959. VariantInit(&varEnrty);
  960. bstrPropName = SysAllocString(lpPropName);
  961. if (!bstrPropName)
  962. {
  963. hr = E_OUTOFMEMORY;
  964. goto exit;
  965. }
  966. hr = pList->GetPropertyItem(bstrPropName, valType, &varEnrty);
  967. hr = V_DISPATCH(&varEnrty)->QueryInterface(IID_IADsPropertyEntry,
  968. (void**)&pEntry);
  969. if (S_OK != hr)
  970. {
  971. pEntry = NULL;
  972. goto exit;
  973. }
  974. VariantInit(&var);
  975. hr = pEntry->get_Values(&var);
  976. if (S_OK != hr)
  977. {
  978. goto exit;
  979. }
  980. LONG dwSLBound = 0;
  981. LONG dwSUBound = 0;
  982. LONG i;
  983. hr = SafeArrayGetLBound(V_ARRAY(&var),1,(long FAR *)&dwSLBound);
  984. if (S_OK != hr)
  985. {
  986. goto exit;
  987. }
  988. hr = SafeArrayGetUBound(V_ARRAY(&var),1,(long FAR *)&dwSUBound);
  989. if (S_OK != hr)
  990. {
  991. goto exit;
  992. }
  993. if (dwSLBound || dwSLBound)
  994. {
  995. //we only interested in one enrty
  996. goto exit;
  997. }
  998. VARIANT v;
  999. VariantInit(&v);
  1000. i = 0;
  1001. hr = SafeArrayGetElement(V_ARRAY(&var),(long FAR *)&i,&v);
  1002. if (FAILED(hr))
  1003. {
  1004. goto exit;
  1005. }
  1006. IDispatch * pDispEntry = V_DISPATCH(&v);
  1007. IADsPropertyValue * pAdsPV = NULL;
  1008. hr = pDispEntry->QueryInterface(IID_IADsPropertyValue,(void **) &pAdsPV);
  1009. if (SUCCEEDED(hr))
  1010. {
  1011. BSTR bValue;
  1012. // Get the value as a BSTR
  1013. hr = GetIADsPropertyValueAsBSTR(&bValue,pEntry,pAdsPV);
  1014. if (hr == S_OK)
  1015. {
  1016. if (lplpValue)
  1017. {
  1018. *lplpValue = (LPTSTR)malloc( (lstrlen(bValue)+1)*sizeof(TCHAR));
  1019. if (!*lplpValue)
  1020. {
  1021. hr = E_OUTOFMEMORY;
  1022. goto exit;
  1023. }
  1024. hr = StringCchCopy(*lplpValue,lstrlen(bValue)+1,bValue);
  1025. }
  1026. }
  1027. }
  1028. if (lpNewValue)
  1029. {
  1030. bstrNewValue = SysAllocString(lpNewValue);
  1031. if (!bstrNewValue)
  1032. {
  1033. hr = E_OUTOFMEMORY;
  1034. goto exit;
  1035. }
  1036. hr = pAdsPV->put_CaseIgnoreString(bstrNewValue);
  1037. }
  1038. i = 0;
  1039. hr = SafeArrayPutElement(V_ARRAY(&var),&i,&v);
  1040. if (hr != S_OK)
  1041. {
  1042. goto exit;
  1043. }
  1044. hr = pEntry->put_ControlCode(ADS_PROPERTY_UPDATE);
  1045. hr = pEntry->put_Values(var);
  1046. pList->PutPropertyItem(varEnrty);
  1047. pObj->SetInfo();
  1048. hr = S_OK;
  1049. exit:;
  1050. if (bstrPropName)
  1051. {
  1052. SysFreeString(bstrPropName);
  1053. }
  1054. if (bstrNewValue)
  1055. {
  1056. SysFreeString(bstrNewValue);
  1057. }
  1058. if (pEntry)
  1059. {
  1060. pEntry->Release();
  1061. }
  1062. if (pObj)
  1063. {
  1064. pObj->Release();
  1065. }
  1066. if (pList)
  1067. {
  1068. pList->Release();
  1069. }
  1070. return hr;
  1071. }
  1072. BOOL UpdateSecurityTemplatesSection (
  1073. LPTSTR lpINFFile,
  1074. LPTSTR lpNewInf,
  1075. LPTSTR lpszSection,
  1076. PREG_STRING_REPLACE lpStrList)
  1077. {
  1078. HRESULT hr = S_OK;
  1079. DWORD cchInSection, CchBufSize, cchOutputSize, cchBufLen;
  1080. DWORD dwAttrib;
  1081. BOOL bUpdated = FALSE;
  1082. LPTSTR lpBuf = NULL;
  1083. LPTSTR lpNewBuf, lpOldBuf, lpLineBuf, lpEnd, lpOutputBuf, lpTemp;
  1084. if (lpINFFile && lpszSection)
  1085. {
  1086. //
  1087. // allocate max size of buffer
  1088. //
  1089. CchBufSize = 0x7FFFF;
  1090. do
  1091. {
  1092. if (lpBuf)
  1093. {
  1094. MEMFREE(lpBuf);
  1095. CchBufSize *= 2;
  1096. }
  1097. lpBuf = (LPTSTR) MEMALLOC(CchBufSize * sizeof(TCHAR));
  1098. if (!lpBuf)
  1099. {
  1100. hr = E_OUTOFMEMORY;
  1101. goto Exit;
  1102. }
  1103. cchInSection = GetPrivateProfileSection(lpszSection,
  1104. lpBuf,
  1105. CchBufSize,
  1106. lpINFFile);
  1107. } while (cchInSection == CchBufSize -2);
  1108. lpEnd = lpBuf;
  1109. lpOutputBuf = NULL;
  1110. cchOutputSize = 0;
  1111. bUpdated = FALSE;
  1112. while(lpEnd < (lpBuf + cchInSection))
  1113. {
  1114. dwAttrib = 0;
  1115. lpNewBuf = ReplaceSingleString (
  1116. lpEnd,
  1117. REG_SZ,
  1118. lpStrList,
  1119. NULL,
  1120. &dwAttrib,
  1121. TRUE);
  1122. if (!lpNewBuf)
  1123. {
  1124. lpNewBuf = ReplaceSingleString (
  1125. lpEnd,
  1126. REG_SZ,
  1127. lpStrList,
  1128. NULL,
  1129. &dwAttrib,
  1130. FALSE);
  1131. }
  1132. if (!lpNewBuf)
  1133. {
  1134. lpLineBuf = lpEnd;
  1135. }
  1136. else
  1137. {
  1138. bUpdated = TRUE;
  1139. lpLineBuf = lpNewBuf;
  1140. if (StrStrI(lpEnd, L"ProgramFiles") && StrStrI(lpNewBuf, L"Programs"))
  1141. {
  1142. //Correct the wrong string replacement
  1143. //the difference between "Programs" and "Program Files" is " File"
  1144. CchBufSize = lstrlen(lpEnd)+6;
  1145. free(lpNewBuf);
  1146. lpNewBuf = (LPTSTR)calloc(CchBufSize, sizeof(TCHAR));
  1147. if (lpNewBuf)
  1148. {
  1149. lpTemp = StrStrI(lpEnd, L"=");
  1150. if (lpTemp)
  1151. {
  1152. *lpTemp = (TCHAR)'\0';
  1153. hr = StringCchCopy(lpNewBuf, CchBufSize, lpEnd);
  1154. *lpTemp = (TCHAR)'=';
  1155. hr = StringCchCat(lpNewBuf, CchBufSize, L"= Program Files");
  1156. lpLineBuf = lpNewBuf;
  1157. if (hr != S_OK)
  1158. DPF(REGerr, L"UpdateSecurityTemplatesSection: StringCchCat failed.");
  1159. }
  1160. else
  1161. {
  1162. free(lpNewBuf);
  1163. lpLineBuf = lpEnd;
  1164. lpNewBuf = NULL;
  1165. bUpdated = FALSE;
  1166. }
  1167. }
  1168. else
  1169. {
  1170. hr = E_OUTOFMEMORY;
  1171. goto Exit;
  1172. }
  1173. }
  1174. }
  1175. cchBufLen = lstrlen(lpLineBuf);
  1176. lpOldBuf = NULL;
  1177. if (lpOutputBuf)
  1178. {
  1179. lpOldBuf = lpOutputBuf;
  1180. lpOutputBuf = (LPTSTR)MEMREALLOC(lpOldBuf, (cchOutputSize+cchBufLen+2)*sizeof(TCHAR));
  1181. }
  1182. else
  1183. {
  1184. lpOutputBuf = (LPTSTR)MEMALLOC((cchBufLen+2)*sizeof(TCHAR));
  1185. cchOutputSize = 0;
  1186. }
  1187. if (lpOutputBuf == NULL)
  1188. {
  1189. if (lpOldBuf)
  1190. MEMFREE(lpOldBuf);
  1191. if (lpBuf)
  1192. MEMFREE(lpBuf);
  1193. if (lpNewBuf)
  1194. free(lpNewBuf);
  1195. hr = E_OUTOFMEMORY;
  1196. goto Exit;
  1197. }
  1198. hr = StringCchCopy(&lpOutputBuf[cchOutputSize], cchBufLen+1, lpLineBuf);
  1199. if (hr != S_OK)
  1200. DPF(REGerr, L"UpdateSecurityTemplatesSection3: failed.");
  1201. cchOutputSize += cchBufLen+1;
  1202. lpEnd += lstrlen(lpEnd)+1;
  1203. if (lpNewBuf)
  1204. free(lpNewBuf);
  1205. }
  1206. if (lpOutputBuf)
  1207. lpOutputBuf[cchOutputSize] = (TCHAR)'\0';
  1208. //Workarround since the function cannot delete the section: Delete the section
  1209. WritePrivateProfileSection (lpszSection, NULL, lpNewInf);
  1210. if (!WritePrivateProfileSection (lpszSection, lpOutputBuf, lpNewInf))
  1211. {
  1212. DPF(INFerr, L"UpdateSecurityTemplatesSection: the section %s in file %s Update failed", lpszSection, lpNewInf);
  1213. }
  1214. if (lpOutputBuf)
  1215. MEMFREE(lpOutputBuf);
  1216. if (lpBuf)
  1217. MEMFREE(lpBuf);
  1218. }
  1219. Exit:
  1220. return bUpdated;
  1221. }
  1222. HRESULT UpdateSecurityTemplates(
  1223. LPTSTR lpINFFile,
  1224. PREG_STRING_REPLACE lpStrList)
  1225. {
  1226. HRESULT hr = E_FAIL;
  1227. DWORD cchRead;
  1228. DWORD cchBuf = 1024;
  1229. LPTSTR lpBuf, lpOldBuf;
  1230. LPTSTR lpSection;
  1231. BOOL bUpdate;
  1232. TCHAR szIndex[16];
  1233. TCHAR szNewInf[MAX_PATH];
  1234. DPF(REGmsg, L"Enter UpdateSecurityTemplates: %s", lpINFFile);
  1235. lpBuf = (LPTSTR)MEMALLOC(cchBuf * sizeof(TCHAR));
  1236. if (lpBuf == NULL)
  1237. {
  1238. return E_OUTOFMEMORY;
  1239. }
  1240. cchRead = GetPrivateProfileSectionNames(lpBuf,
  1241. cchBuf,
  1242. lpINFFile);
  1243. while (cchRead == (cchBuf - 2))
  1244. {
  1245. // Buffer is too small, reallocate until we have enough
  1246. lpOldBuf = lpBuf;
  1247. cchBuf += 1024;
  1248. lpBuf = (LPTSTR)MEMREALLOC(lpOldBuf, cchBuf * sizeof(TCHAR));
  1249. if (lpBuf == NULL)
  1250. {
  1251. MEMFREE(lpOldBuf);
  1252. return E_OUTOFMEMORY;
  1253. }
  1254. // Read the data from section again
  1255. cchRead = GetPrivateProfileSectionNames(lpBuf,
  1256. cchBuf,
  1257. lpINFFile);
  1258. }
  1259. // At this point we have big enough buffer and data in it
  1260. if (cchRead > 0)
  1261. {
  1262. hr = StringCchPrintf(szNewInf, MAX_PATH, TEXT("%s.clmt"), lpINFFile);
  1263. CopyFile(lpINFFile, szNewInf, FALSE);
  1264. lpSection = (LPTSTR)MultiSzTok(lpBuf);
  1265. bUpdate = FALSE;
  1266. while (lpSection != NULL)
  1267. {
  1268. if (UpdateSecurityTemplatesSection(lpINFFile, szNewInf, lpSection, lpStrList))
  1269. {
  1270. bUpdate = TRUE;
  1271. DPF(INFmsg, L"UpdateSecurityTemplatesSection: the section %s in file %s Updated", lpSection, lpINFFile);
  1272. }
  1273. // Get next section name
  1274. lpSection = (LPTSTR)MultiSzTok(NULL);
  1275. }
  1276. if (bUpdate)
  1277. {
  1278. g_dwKeyIndex++;
  1279. _itot(g_dwKeyIndex,szIndex,16);
  1280. if (!WritePrivateProfileString(TEXT("INF Update"),szIndex,szNewInf,g_szToDoINFFileName))
  1281. {
  1282. hr = HRESULT_FROM_WIN32(GetLastError());
  1283. }
  1284. }
  1285. }
  1286. else
  1287. {
  1288. SetLastError(ERROR_NOT_FOUND);
  1289. }
  1290. MEMFREE(lpBuf);
  1291. DPF(REGmsg, L"Exit UpdateSecurityTemplates:");
  1292. return hr;
  1293. }
  1294. HRESULT BatchINFUpdate(HINF hInf)
  1295. {
  1296. HRESULT hr = S_OK;
  1297. UINT LineCount,LineNo;
  1298. DWORD dwRequired;
  1299. INFCONTEXT InfContext;
  1300. LPTSTR lpTemp;
  1301. LPTSTR lpszSection = TEXT("INF Update");
  1302. TCHAR chTemp;
  1303. TCHAR szFileNameIn[MAX_PATH];
  1304. TCHAR szFileNameOut[MAX_PATH];
  1305. DPF(INFmsg ,TEXT("Enter BatchINFUpdate:"));
  1306. if ((hInf == INVALID_HANDLE_VALUE))
  1307. {
  1308. hr = E_INVALIDARG;
  1309. goto Exit;
  1310. }
  1311. LineCount = (UINT)SetupGetLineCount(hInf,lpszSection);
  1312. if ((LONG)LineCount <= 0)
  1313. {
  1314. hr = S_FALSE;
  1315. DPF(INFwar ,TEXT("BatchINFUpdate: failed. Section %s is empty!"),lpszSection);
  1316. goto Exit;
  1317. }
  1318. for(LineNo=0; LineNo<LineCount; LineNo++)
  1319. {
  1320. if (!SetupGetLineByIndex(hInf,lpszSection,LineNo,&InfContext))
  1321. {
  1322. DPF(INFerr ,TEXT("BatchINFUpdate: can not get line %n of section %s !"),LineNo, lpszSection);
  1323. hr = E_FAIL;
  1324. goto Exit;
  1325. }
  1326. if (!SetupGetStringField(&InfContext,1,szFileNameIn,MAX_PATH,&dwRequired))
  1327. {
  1328. DPF(INFerr ,TEXT("BatchINFUpdate: get [%s] 's line %d 's Field 1 failed !"),lpszSection, LineNo);
  1329. hr = E_FAIL;
  1330. goto Exit;
  1331. }
  1332. lpTemp = StrStrI(szFileNameIn, TEXT(".clmt"));
  1333. if (lpTemp)
  1334. {
  1335. *lpTemp = (TCHAR)'\0';
  1336. hr = StringCchPrintf(szFileNameOut, MAX_PATH, TEXT("%s.bak"), szFileNameIn);
  1337. MoveFile(szFileNameIn, szFileNameOut);
  1338. hr = StringCchCopy(szFileNameOut, MAX_PATH, szFileNameIn);
  1339. *lpTemp = (TCHAR)'.';
  1340. MoveFile(szFileNameIn, szFileNameOut);
  1341. DPF(INFinf ,TEXT("BatchINFUpdate: %s is updated and backup file is %s.bak"), szFileNameOut, szFileNameOut);
  1342. }
  1343. }
  1344. Exit:
  1345. DPF(INFmsg ,TEXT("Exit BatchINFUpdate: hr = %d"), hr);
  1346. return hr;
  1347. }