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.

1304 lines
47 KiB

  1. #include "StdAfx.h"
  2. #include "clmt.h"
  3. HRESULT VerifyRegistryLinesWithSystemRegistry(HKEY, HINF, LPCTSTR, BOOL*);
  4. HRESULT UpdateSystemRegistryWithRegistryLines(HKEY, HINF, LPCTSTR, LPCTSTR);
  5. HRESULT CheckAndAddHardLinkLine(HINF, LPCTSTR, LPTSTR);
  6. #define FOLDER(csidl, strid,ids, valuename) \
  7. { csidl, strid, ids, valuename}
  8. FOLDER_INFO c_rgFolderInfo[] =
  9. {
  10. FOLDER( CSIDL_DESKTOPDIRECTORY,
  11. TEXT("CSIDL_DESKTOPDIRECTORY"),
  12. 0,
  13. TEXT("Desktop")),
  14. // _STARTUP is a subfolder of _PROGRAMS is a subfolder of _STARTMENU -- keep that order
  15. FOLDER( CSIDL_STARTUP,
  16. TEXT("CSIDL_STARTUP"),
  17. 0,
  18. TEXT("Startup")),
  19. FOLDER( CSIDL_PROGRAMS,
  20. TEXT("CSIDL_PROGRAMS"),
  21. 0,
  22. TEXT("Programs")),
  23. FOLDER( CSIDL_STARTMENU,
  24. TEXT("CSIDL_STARTMENU"),
  25. 0,
  26. TEXT("Start Menu")),
  27. FOLDER( CSIDL_RECENT,
  28. TEXT("CSIDL_RECENT"),
  29. 0,
  30. TEXT("Recent")),
  31. FOLDER( CSIDL_SENDTO,
  32. TEXT("CSIDL_SENDTO"),
  33. 0,
  34. TEXT("SendTo")),
  35. FOLDER( CSIDL_PERSONAL,
  36. TEXT("CSIDL_PERSONAL"),
  37. 0,
  38. TEXT("Personal")),
  39. FOLDER( CSIDL_FAVORITES,
  40. TEXT("CSIDL_FAVORITES"),
  41. 0,
  42. TEXT("Favorites")),
  43. FOLDER( CSIDL_NETHOOD,
  44. TEXT("CSIDL_NETHOOD"),
  45. 0,
  46. TEXT("NetHood")),
  47. FOLDER( CSIDL_PRINTHOOD,
  48. TEXT("CSIDL_PRINTHOOD"),
  49. 0,
  50. TEXT("PrintHood")),
  51. FOLDER( CSIDL_TEMPLATES,
  52. TEXT("CSIDL_TEMPLATES"),
  53. 0,
  54. TEXT("Templates")),
  55. // Common special folders
  56. // _STARTUP is a subfolder of _PROGRAMS is a subfolder of _STARTMENU -- keep that order
  57. FOLDER( CSIDL_COMMON_STARTUP,
  58. TEXT("CSIDL_COMMON_STARTUP"),
  59. 0,
  60. TEXT("Common Startup")),
  61. FOLDER( CSIDL_COMMON_PROGRAMS,
  62. TEXT("CSIDL_COMMON_PROGRAMS"),
  63. 0,
  64. TEXT("Common Programs")),
  65. FOLDER( CSIDL_COMMON_STARTMENU,
  66. TEXT("CSIDL_COMMON_STARTMENU"),
  67. 0,
  68. TEXT("Common Start Menu")),
  69. FOLDER( CSIDL_COMMON_DESKTOPDIRECTORY,
  70. TEXT("CSIDL_COMMON_DESKTOPDIRECTORY"),
  71. 0,
  72. TEXT("Common Desktop")),
  73. FOLDER( CSIDL_COMMON_FAVORITES,
  74. TEXT("CSIDL_COMMON_FAVORITES"),
  75. 0,
  76. TEXT("Common Favorites")),
  77. FOLDER( CSIDL_COMMON_APPDATA,
  78. TEXT("CSIDL_COMMON_APPDATA"),
  79. 0,
  80. TEXT("Common AppData")),
  81. FOLDER( CSIDL_COMMON_TEMPLATES,
  82. TEXT("CSIDL_COMMON_TEMPLATES"),
  83. 0,
  84. TEXT("Common Templates")),
  85. FOLDER( CSIDL_COMMON_DOCUMENTS,
  86. TEXT("CSIDL_COMMON_DOCUMENTS"),
  87. 0,
  88. TEXT("Common Documents")),
  89. // Application Data special folder
  90. FOLDER( CSIDL_APPDATA,
  91. TEXT("CSIDL_APPDATA"),
  92. 0,
  93. TEXT("AppData")),
  94. FOLDER( CSIDL_LOCAL_APPDATA,
  95. TEXT("CSIDL_LOCAL_APPDATA"),
  96. 0,
  97. TEXT("Local AppData")),
  98. // Per-user Internet-related folders
  99. FOLDER( CSIDL_INTERNET_CACHE,
  100. TEXT("CSIDL_INTERNET_CACHE"),
  101. 0,
  102. TEXT("Cache")),
  103. FOLDER( CSIDL_COOKIES,
  104. TEXT("CSIDL_COOKIES"),
  105. 0,
  106. TEXT("Cookies")),
  107. FOLDER( CSIDL_HISTORY,
  108. TEXT("CSIDL_HISTORY"),
  109. 0,
  110. TEXT("History")),
  111. FOLDER( CSIDL_MYPICTURES,
  112. TEXT("CSIDL_MYPICTURES"),
  113. 0,
  114. TEXT("My Pictures")),
  115. FOLDER( CSIDL_ADMINTOOLS,
  116. TEXT("CSIDL_ADMINTOOLS"),
  117. 0,
  118. TEXT("Administrative Tools")),
  119. FOLDER( CSIDL_COMMON_ADMINTOOLS,
  120. TEXT("CSIDL_COMMON_ADMINTOOLS"),
  121. 0,
  122. TEXT("Common Administrative Tools")),
  123. FOLDER( CSIDL_MYMUSIC,
  124. TEXT("CSIDL_MYMUSIC"),
  125. 0,
  126. TEXT("My Music")),
  127. FOLDER( CSIDL_COMMON_PICTURES,
  128. TEXT("CSIDL_COMMON_PICTURES"),
  129. 0,
  130. TEXT("CommonPictures")),
  131. FOLDER( CSIDL_COMMON_MUSIC,
  132. TEXT("CSIDL_COMMON_MUSIC"),
  133. 0,
  134. TEXT("CommonMusic")),
  135. //Private defined ID , points to %USERPROFILE%\Local Settings
  136. FOLDER( CSIDL_QUICKLAUNCH,
  137. TEXT("CSIDL_QUICKLAUNCH"),
  138. 0,
  139. TEXT("Quick Launch")),
  140. FOLDER( CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES,
  141. TEXT("CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES"),
  142. 0,
  143. TEXT("Services")),
  144. FOLDER( CSIDL_COMMON_PROGRAMFILES_ACCESSARIES,
  145. TEXT("CSIDL_COMMON_PROGRAMFILES_ACCESSARIES"),
  146. 0,
  147. TEXT("Accessaries")),
  148. FOLDER( CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES,
  149. TEXT("CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES"),
  150. 0,
  151. TEXT("Accessaries")),
  152. FOLDER( CSIDL_LOCAL_SETTINGS,
  153. TEXT("CSIDL_LOCAL_SETTINGS"),
  154. 0,
  155. TEXT("Local Settings")),
  156. //Private defined ID , points to %ALLUSERSPROFILE%\%Start_Menu%\%Programs%\%Accessories%
  157. FOLDER( CSIDL_COMMON_ACCESSORIES,
  158. TEXT("CSIDL_COMMON_ACCESSORIES"),
  159. 0,
  160. TEXT("Local Settings")),
  161. //Private defined ID , points to "%USERPROFILE%\%Start_Menu%\%Programs%\%Accessories%
  162. FOLDER( CSIDL_ACCESSORIES,
  163. TEXT("CSIDL_ACCESSORIES"),
  164. 0,
  165. TEXT("Local Settings")),
  166. FOLDER( CSIDL_PF_ACCESSORIES,
  167. TEXT("CSIDL_PF_ACCESSORIES"),
  168. 0,
  169. TEXT("PF_AccessoriesName")),
  170. FOLDER( CSIDL_PROGRAM_FILES_COMMON,
  171. TEXT("CSIDL_PROGRAM_FILES_COMMON"),
  172. 0,
  173. TEXT("CommonFilesDir")),
  174. FOLDER( CSIDL_PROGRAM_FILES,
  175. TEXT("CSIDL_PROGRAM_FILES"),
  176. 0,
  177. TEXT("ProgramFilesDir")),
  178. FOLDER( CSIDL_PROFILES_DIRECTORY,
  179. TEXT("CSIDL_PROFILES_DIRECTORY"),
  180. 0,
  181. TEXT("ProfilesDirectory")),
  182. //Private defined ID , points to "%USERPROFILE%\%Start_Menu%\%Programs%\%Accessories%
  183. FOLDER( CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY,
  184. TEXT("CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY"),
  185. 0,
  186. TEXT("ProfilesDirectory")),
  187. FOLDER( CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT,
  188. TEXT("CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT"),
  189. 0,
  190. TEXT("ProfilesDirectory")),
  191. FOLDER( CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS,
  192. TEXT("CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS"),
  193. 0,
  194. TEXT("ProfilesDirectory")),
  195. FOLDER( CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS,
  196. TEXT("CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS"),
  197. 0,
  198. TEXT("ProfilesDirectory")),
  199. FOLDER( CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER,
  200. TEXT("CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER"),
  201. 0,
  202. TEXT("ProfilesDirectory")),
  203. FOLDER( CSIDL_COMMON_ACCESSORIES_GAMES,
  204. TEXT("CSIDL_COMMON_ACCESSORIES_GAMES"),
  205. 0,
  206. TEXT("ProfilesDirectory")),
  207. FOLDER( CSIDL_COMMON_WINDOWSMEDIA,
  208. TEXT("CSIDL_COMMON_WINDOWSMEDIA"),
  209. 0,
  210. TEXT("ProfilesDirectory")),
  211. FOLDER( CSIDL_COMMON_COVERPAGES,
  212. TEXT("CSIDL_COMMON_COVERPAGES"),
  213. 0,
  214. TEXT("ProfilesDirectory")),
  215. FOLDER( CSIDL_COMMON_RECEIVED_FAX,
  216. TEXT("CSIDL_COMMON_RECEIVED_FAX"),
  217. 0,
  218. TEXT("ProfilesDirectory")),
  219. FOLDER( CSIDL_COMMON_SENT_FAX,
  220. TEXT("CSIDL_COMMON_SENT_FAX"),
  221. 0,
  222. TEXT("ProfilesDirectory")),
  223. FOLDER( CSIDL_COMMON_FAX,
  224. TEXT("CSIDL_COMMON_FAX"),
  225. 0,
  226. TEXT("ProfilesDirectory")),
  227. FOLDER( CSIDL_COMMON_PICTURES,
  228. TEXT("CSIDL_COMMON_PICTURES"),
  229. 0,
  230. TEXT("ProfilesDirectory")),
  231. FOLDER( CSIDL_FAVORITES_LINKS,
  232. TEXT("CSIDL_FAVORITES_LINKS"),
  233. 0,
  234. TEXT("ProfilesDirectory")),
  235. FOLDER( CSIDL_FAVORITES_MEDIA,
  236. TEXT("CSIDL_FAVORITES_MEDIA"),
  237. 0,
  238. TEXT("ProfilesDirectory")),
  239. FOLDER( CSIDL_ACCESSORIES_ACCESSIBILITY,
  240. TEXT("CSIDL_ACCESSORIES_ACCESSIBILITY"),
  241. 0,
  242. TEXT("ProfilesDirectory")),
  243. FOLDER( CSIDL_ACCESSORIES_SYSTEM_TOOLS,
  244. TEXT("CSIDL_ACCESSORIES_SYSTEM_TOOLS"),
  245. 0,
  246. TEXT("ProfilesDirectory")),
  247. FOLDER( CSIDL_ACCESSORIES_ENTERTAINMENT,
  248. TEXT("CSIDL_ACCESSORIES_ENTERTAINMENT"),
  249. 0,
  250. TEXT("ProfilesDirectory")),
  251. FOLDER( CSIDL_ACCESSORIES_COMMUNICATIONS,
  252. TEXT("CSIDL_ACCESSORIES_COMMUNICATIONS"),
  253. 0,
  254. TEXT("ProfileDirectory")),
  255. FOLDER( CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL,
  256. TEXT("CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL"),
  257. 0,
  258. TEXT("ProfileDirectory")),
  259. FOLDER( CSIDL_UAM_VOLUME,
  260. TEXT("CSIDL_UAM_VOLUME"),
  261. 0,
  262. TEXT("Microsoft UAM Volume")),
  263. FOLDER( CSIDL_COMMON_SHAREDTOOLS_STATIONERY,
  264. TEXT("CSIDL_COMMON_SHAREDTOOLS_STATIONERY"),
  265. 0,
  266. TEXT("Stationery")),
  267. FOLDER( CSIDL_NETMEETING_RECEIVED_FILES,
  268. TEXT("CSIDL_NETMEETING_RECEIVED_FILES"),
  269. 0,
  270. TEXT("Received Files")),
  271. FOLDER( CSIDL_COMMON_NETMEETING_RECEIVED_FILES,
  272. TEXT("CSIDL_COMMON_NETMEETING_RECEIVED_FILES"),
  273. 0,
  274. TEXT("Received Files")),
  275. FOLDER( CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX,
  276. TEXT("CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX"),
  277. 0,
  278. TEXT("Fax")),
  279. FOLDER( CSIDL_FAX_PERSONAL_COVER_PAGES,
  280. TEXT("CSIDL_FAX_PERSONAL_COVER_PAGES"),
  281. 0,
  282. TEXT("Personal Coverpages")),
  283. FOLDER( CSIDL_FAX,
  284. TEXT("CSIDL_FAX"),
  285. 0,
  286. TEXT("Fax")),
  287. FOLDER (-1, NULL, 0, NULL)
  288. };
  289. /*++
  290. Routine Description:
  291. This routine does the shell folder renaming, notice folders may not be strictly
  292. Shell folder, since we extended CSIDL_????? by adding out private one in .h file
  293. Arguments:
  294. csidl - shell ID(maybe our private one )
  295. hKeyRoot - Registry Key
  296. hInf - INF file handle
  297. szUserName - user name hKeyRoot belongs to
  298. Return Value:
  299. S_OK if succeeds
  300. --*/
  301. HRESULT FixFolderPath(
  302. INT csidl,
  303. HKEY hKeyRoot,
  304. HINF hInf,
  305. LPTSTR szUserName,
  306. BOOL bCreateHardLink)
  307. {
  308. const FOLDER_INFO *pfi;
  309. HRESULT hr;
  310. HKEY hk = NULL;
  311. TCHAR szSection[MAX_PATH];
  312. INFCONTEXT context ;
  313. TCHAR szTypeReg[MAX_PATH];
  314. TCHAR szKeyReg[MAX_PATH];
  315. TCHAR szValueNameReg[MAX_PATH];
  316. TCHAR szOrgValueReg[MAX_PATH];
  317. TCHAR szNewValueReg[MAX_PATH];
  318. DWORD dwTypeReg;
  319. int nOriIndexFldr,nNewIndexFldr;
  320. TCHAR szPlatformFldr[MAX_PATH];
  321. TCHAR szTypeFldr[MAX_PATH];
  322. TCHAR szOrgValueFldr[MAX_PATH];
  323. TCHAR szNewValueFldr[MAX_PATH];
  324. DWORD dwPlatformFldr;
  325. DWORD dwTypeFldr;
  326. DWORD dwAttrib = 0;
  327. TCHAR szPathInReg[2*MAX_PATH];
  328. LONG lStatus;
  329. HKEY hKey;
  330. LPTSTR pSubKeyPath;
  331. DWORD dwSize;
  332. LPTSTR pExcluseFileList = NULL;
  333. BOOL bRegistryLineAvailable = TRUE;
  334. TCHAR szOrgLongPath[MAX_PATH],szNewLongPath[MAX_PATH];
  335. TCHAR szOrgShortPath[MAX_PATH],szNewShortPath[MAX_PATH];
  336. TCHAR szOrgShortPathTemplate[MAX_PATH],szNewShortPathTemplate[MAX_PATH];
  337. TCHAR szFullPath[MAX_PATH];
  338. int nOrgPathTemplate,nNewPathTemplate;
  339. PREG_STRING_REPLACE pCurrTable;
  340. //If INF file handle is invalid, just return
  341. if (!hInf)
  342. {
  343. hr = E_INVALIDARG;
  344. goto Cleanup;
  345. }
  346. //Try to search ID table ,see whether it's valid
  347. for (pfi = c_rgFolderInfo; pfi->id != -1; pfi++)
  348. {
  349. if (pfi->id == csidl)
  350. {
  351. break;
  352. }
  353. }
  354. //if it's not in our pre-defined id table, return with failure
  355. if (pfi->id == -1 )
  356. {
  357. hr = E_INVALIDARG;
  358. goto Cleanup;
  359. }
  360. //Get the ID section name in INF file eg. [ShellFolder.CSIDL_COOKIES]
  361. hr = StringCchCopy(szSection,MAX_PATH,SHELL_FOLDER_PREFIX);
  362. if (FAILED(hr))
  363. {
  364. goto Cleanup;
  365. }
  366. hr = StringCchCat(szSection,MAX_PATH,pfi->pszIdInString);
  367. if (FAILED(hr))
  368. {
  369. goto Cleanup;
  370. }
  371. //In folder line , the 3rd field is localized folder name
  372. // the 4th field is english folder name
  373. //In the case of we are running before migration and in undo mode
  374. //the source is English string , while the new string should be localized one
  375. nOriIndexFldr = 3;
  376. nNewIndexFldr = 4;
  377. nOrgPathTemplate = 1;
  378. nNewPathTemplate = 2;
  379. pCurrTable = &g_StrReplaceTable;
  380. // RERKBOOS: Change here!!!
  381. //
  382. // Check if there is a Registry line for this CSIDL_XXX section or not
  383. // If there is, check if we need to modify system registry following the
  384. // Registry line or not
  385. //
  386. hr = VerifyRegistryLinesWithSystemRegistry(hKeyRoot,
  387. hInf,
  388. szSection,
  389. &bRegistryLineAvailable);
  390. if (hr != S_OK)
  391. {
  392. goto Cleanup;
  393. }
  394. //if we arrive here , it means we need to rename that folder
  395. //Before we change folder, we need to know the original path's shortpatt
  396. //value
  397. hr = StringCchCopy(szOrgLongPath,MAX_PATH,TEXT(""));
  398. hr = StringCchCopy(szNewLongPath,MAX_PATH,TEXT(""));
  399. hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
  400. hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
  401. if (SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_LONGPATH_TEMPLATE,&context))
  402. {
  403. if (!SetupGetStringField(&context,nOrgPathTemplate,szOrgLongPath,MAX_PATH,NULL)
  404. || !SetupGetStringField(&context,nNewPathTemplate,szNewLongPath,MAX_PATH,NULL))
  405. {
  406. hr = StringCchCopy(szOrgLongPath,MAX_PATH,TEXT(""));
  407. hr = StringCchCopy(szNewLongPath,MAX_PATH,TEXT(""));
  408. }
  409. }
  410. if (SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_SHORTPATH_TEMPLATE,&context))
  411. {
  412. if (!SetupGetStringField(&context,nOrgPathTemplate,szOrgShortPathTemplate,MAX_PATH,NULL)
  413. || !SetupGetStringField(&context,nNewPathTemplate,szNewShortPathTemplate,MAX_PATH,NULL))
  414. {
  415. hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
  416. hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
  417. hr = StringCchCopy(szFullPath,ARRAYSIZE(szFullPath),TEXT(""));
  418. }
  419. else
  420. {
  421. hr = StringCchCopy(szFullPath,ARRAYSIZE(szFullPath),szOrgShortPathTemplate);
  422. if (!GetShortPathName(szOrgShortPathTemplate,szOrgShortPath,MAX_PATH))
  423. {
  424. hr = StringCchCopy(szOrgShortPathTemplate,MAX_PATH,TEXT(""));
  425. hr = StringCchCopy(szNewShortPathTemplate,MAX_PATH,TEXT(""));
  426. }
  427. }
  428. }
  429. //Get the first folder line for the section just found
  430. if (!SetupFindFirstLine(hInf, szSection,SHELL_FOLDER_FOLDER,&context))
  431. {
  432. DWORD dw = GetLastError();
  433. hr = HRESULT_FROM_WIN32(dw);
  434. DPF (dlError,TEXT("can not find folder Key in section [%s] error %n"),szSection,dw);
  435. goto Cleanup;
  436. }
  437. do
  438. {
  439. //Folder Line has 4 basic fields
  440. //Field 1 :Platform means whether this should be excuted
  441. // 0 = should be run both before and after migration
  442. // 1 = should be run only after migration
  443. // 2 = should be run only before migration
  444. //Field 2 :Type means whether it's a folder op or file op
  445. // 0 = foler opration
  446. // 1 = file opration
  447. //Field 3/4:Original and new folder name
  448. //String after Field 4 : This only happens when run after migration,
  449. //it contains a list of files/folders that we need to delete in original
  450. //folder before we move to new folder
  451. if (!SetupGetStringField(&context,1,szPlatformFldr,MAX_PATH,NULL)
  452. || !SetupGetStringField(&context,2,szTypeFldr,MAX_PATH,NULL)
  453. || ! SetupGetStringField(&context,nOriIndexFldr,szOrgValueFldr,MAX_PATH,NULL)
  454. || ! SetupGetStringField(&context,nNewIndexFldr,szNewValueFldr,MAX_PATH,NULL))
  455. {
  456. DWORD dw = GetLastError();
  457. hr = HRESULT_FROM_WIN32(dw);
  458. DPF(dlError,TEXT("get registry info failed in [%n],line %n with %n !"),context.Section ,context.Line,dw);
  459. goto Cleanup;
  460. }
  461. dwPlatformFldr = _tstoi(szPlatformFldr);
  462. dwTypeFldr = _tstoi(szTypeFldr);
  463. if (!g_bBeforeMig )
  464. {
  465. if (dwPlatformFldr == 2)
  466. {
  467. continue;
  468. }
  469. //running after migration, we try to get exclude folder list in MultiSZ
  470. //if it's a folder entry
  471. if (dwTypeFldr == 0)
  472. {
  473. BOOL bTmp;
  474. bTmp = SetupGetMultiSzField(&context,5,NULL,0,&dwSize);
  475. if ( bTmp && (dwSize > 1) )
  476. {
  477. LPTSTR p;
  478. pExcluseFileList = malloc(dwSize * sizeof(TCHAR));
  479. if (!pExcluseFileList)
  480. {
  481. goto Cleanup;
  482. }
  483. if (!SetupGetMultiSzField(&context,5,pExcluseFileList,dwSize,&dwSize))
  484. {
  485. goto Cleanup;
  486. }
  487. p = pExcluseFileList;
  488. //loop MulitSZ string and delete each file/folder
  489. while (*p)
  490. {
  491. TCHAR szTmpFile[2*MAX_PATH];
  492. hr = StringCchCopy(szTmpFile,2*MAX_PATH,szOrgValueFldr);
  493. ConcatenatePaths(szTmpFile,p,MAX_PATH);
  494. DeleteFile(szTmpFile);
  495. p += (lstrlen(p)+1);
  496. }
  497. free(pExcluseFileList);
  498. pExcluseFileList = NULL;
  499. }
  500. }
  501. }
  502. else
  503. {
  504. if (dwPlatformFldr == 1)
  505. {
  506. continue;
  507. }
  508. }
  509. if (dwTypeFldr == 0)
  510. {
  511. hr = MyMoveDirectory(szOrgValueFldr,szNewValueFldr,TRUE,TRUE,bCreateHardLink,pfi->id);
  512. if (hr != S_OK)
  513. {
  514. if (FAILED(hr))
  515. {
  516. DPF (dlError,TEXT("can not move folder from %s to %s Error: %d (%#x)"),
  517. szOrgValueFldr,szNewValueFldr,hr,hr);
  518. }
  519. goto Cleanup;
  520. }
  521. }
  522. else
  523. if (dwTypeFldr == 1)
  524. {
  525. hr = MyMoveFile(szOrgValueFldr,szNewValueFldr,TRUE,FALSE);
  526. //hr = MyMoveFile(szOrgValueFldr,szNewValueFldr,FALSE,FALSE);
  527. if (FAILED(hr))
  528. {
  529. DPF (dlError,TEXT("can not move file from %s to %s "),szOrgValueFldr,szNewValueFldr);
  530. goto Cleanup;
  531. }
  532. }
  533. }while (SetupFindNextMatchLine(&context,SHELL_FOLDER_FOLDER,&context));
  534. CheckAndAddHardLinkLine(hInf,szSection,szUserName);
  535. //If we arrive here, we can update the registry now
  536. if (bRegistryLineAvailable)
  537. {
  538. hr = UpdateSystemRegistryWithRegistryLines(hKeyRoot,
  539. hInf,
  540. szSection,
  541. szUserName);
  542. }
  543. if (szOrgLongPath[0])
  544. {
  545. if (!AddItemToStrRepaceTable(szUserName,szOrgLongPath,szNewLongPath,szFullPath,pfi->id,pCurrTable))
  546. {
  547. hr = E_OUTOFMEMORY;
  548. goto Cleanup;
  549. }
  550. }
  551. if (szOrgShortPathTemplate[0])
  552. {
  553. TCHAR *lpOldName,*lpNewName;
  554. TCHAR szRoot[MAX_PATH],szOldShortPath[MAX_PATH];
  555. TCHAR *lpOldShortName,szNewShortName[MAX_PATH];
  556. if (GetShortPathName(szOrgShortPathTemplate,szOldShortPath,ARRAYSIZE(szOldShortPath)))
  557. {
  558. lpOldName = _tcsrchr(szOrgShortPathTemplate,TEXT('\\'));
  559. lpNewName = _tcsrchr(szNewShortPathTemplate,TEXT('\\'));
  560. lpOldShortName = _tcsrchr(szOldShortPath,TEXT('\\'));
  561. if (lpOldName && lpNewName && lpOldShortName)
  562. {
  563. *lpOldName = TEXT('\0');
  564. hr = StringCchCopy(szRoot,ARRAYSIZE(szRoot),szOrgShortPathTemplate);
  565. *lpOldName = TEXT('\\');
  566. hr = MyGetShortPathName(szRoot,lpOldName+1,lpNewName+1,
  567. szNewShortName,ARRAYSIZE(szNewShortName));
  568. if ( (S_OK == hr) && MyStrCmpI(lpOldShortName,szNewShortName))
  569. {
  570. if (!AddItemToStrRepaceTable(szUserName,
  571. lpOldShortName+1,
  572. szNewShortName,
  573. szOldShortPath,
  574. pfi->id|0xffff0000,
  575. pCurrTable))
  576. {
  577. hr = E_OUTOFMEMORY;
  578. goto Cleanup;
  579. }
  580. }
  581. }
  582. }
  583. }
  584. hr = S_OK;
  585. Cleanup:
  586. if (pExcluseFileList)
  587. {
  588. free(pExcluseFileList);
  589. }
  590. return (hr);
  591. }
  592. /*++
  593. Routine Description:
  594. This routine does the shell folder renaming, notice folders may not be strictly
  595. Shell folder, since we extended CSIDL_????? by adding out private one in .h file
  596. Arguments:
  597. hInf - INF file Handle
  598. hKey - Registry Key
  599. szUsername - user name the hKey belongs to
  600. Return Value:
  601. NULL
  602. --*/
  603. HRESULT DoShellFolderRename(HINF hInf, HKEY hKey, LPTSTR szUsername)
  604. {
  605. TCHAR szSection[MAX_PATH];
  606. UINT LineCount,LineNo;
  607. INFCONTEXT InfContext;
  608. TCHAR szShellCSIDL[MAX_PATH];
  609. const FOLDER_INFO *pfi;
  610. PREG_STRING_REPLACE pCurrTable;
  611. HRESULT hr;
  612. TCHAR szHardLink[MAX_PATH];
  613. BOOL bErrorOccured = FALSE;
  614. #define STRING_SHELL_FOLDER_PROCESS_PERUSER TEXT("Shell.Folders.RenameList.PerUser")
  615. #define STRING_SHELL_FOLDER_PROCESS_PERSYS TEXT("Shell.Folders.RenameList.PerSystem")
  616. #define ID_SHELL_FOLDER_PROCESS_PERUSER 0
  617. #define ID_SHELL_FOLDER_PROCESS_PERSYS 1
  618. if(hInf == INVALID_HANDLE_VALUE)
  619. {
  620. hr = E_INVALIDARG;
  621. goto Cleanup;
  622. }
  623. if (hKey)
  624. {
  625. hr = StringCchCopy(szSection,MAX_PATH,STRING_SHELL_FOLDER_PROCESS_PERUSER);
  626. if (FAILED(hr))
  627. {
  628. goto Cleanup;
  629. }
  630. }
  631. else
  632. {
  633. hr = StringCchCopy(szSection,MAX_PATH,STRING_SHELL_FOLDER_PROCESS_PERSYS);
  634. if (FAILED(hr))
  635. {
  636. goto Cleanup;
  637. }
  638. }
  639. LineCount = (UINT)SetupGetLineCount(hInf,szSection);
  640. if ((LONG)LineCount < 0)
  641. {
  642. hr = S_FALSE;
  643. goto Cleanup;
  644. }
  645. pCurrTable = &g_StrReplaceTable;
  646. for(LineNo=0; LineNo<LineCount; LineNo++)
  647. {
  648. BOOL bCreateHardLink = FALSE;
  649. if (!SetupGetLineByIndex(hInf,szSection,LineNo,&InfContext))
  650. {
  651. continue;
  652. }
  653. if (!SetupGetStringField(&InfContext,1,szShellCSIDL,MAX_PATH,NULL))
  654. {
  655. continue;
  656. }
  657. //Try to search ID table ,see whether it's valid
  658. for (pfi = c_rgFolderInfo; pfi->id != -1; pfi++)
  659. {
  660. if (!MyStrCmpI(pfi->pszIdInString,szShellCSIDL))
  661. {
  662. break;
  663. }
  664. }
  665. if (pfi->id == -1 )
  666. {
  667. continue;
  668. }
  669. if (SetupGetStringField(&InfContext,2,szHardLink,MAX_PATH,NULL))
  670. {
  671. bCreateHardLink = TRUE;
  672. }
  673. hr = FixFolderPath(pfi->id, hKey,hInf,szUsername,bCreateHardLink);
  674. if (FAILED(hr))
  675. {
  676. bErrorOccured = TRUE;
  677. }
  678. }
  679. if (bErrorOccured)
  680. {
  681. hr = E_FAIL;
  682. }
  683. else
  684. {
  685. hr = S_OK;
  686. }
  687. Cleanup:
  688. return hr;;
  689. }
  690. HRESULT VerifyRegistryLinesWithSystemRegistry(
  691. HKEY hKeyRoot,
  692. HINF hInf,
  693. LPCTSTR lpSection,
  694. BOOL *pbRegistryLineAvailable
  695. )
  696. {
  697. HRESULT hr = S_OK;
  698. BOOL bRet;
  699. LONG lRet;
  700. INFCONTEXT context;
  701. BOOL bRegistryLineAvailable;
  702. BOOL bNeedRegReset = TRUE;
  703. TCHAR szResetType[4];
  704. TCHAR szRegType[4];
  705. TCHAR szValueName[MAX_PATH];
  706. TCHAR szNewValueName[MAX_PATH];
  707. TCHAR szNewRegKeyName[MAX_PATH];
  708. TCHAR szRegKey[MAX_PATH];
  709. TCHAR szOldValue[512];
  710. TCHAR szNewValue[512];
  711. TCHAR szValueInReg[512];
  712. HKEY hKey;
  713. LPTSTR lpSubKeyPath;
  714. LPTSTR lpEnd;
  715. DWORD cbValueInReg;
  716. DWORD dwResetType;
  717. DWORD dwRegType;
  718. DWORD dwType;
  719. // Get the Registry Lines for the section just found
  720. bRet = SetupFindFirstLine(hInf, lpSection, SHELL_FOLDER_REGISTRY, &context);
  721. if (!bRet)
  722. {
  723. hr = HRESULT_FROM_WIN32(GetLastError());
  724. DPF(dlError,
  725. TEXT("Cannot find Registry Key in section [%s], hr = 0x%X"),
  726. lpSection,
  727. hr);
  728. goto EXIT;
  729. }
  730. *pbRegistryLineAvailable = FALSE;
  731. bNeedRegReset = TRUE;
  732. while (bRet)
  733. {
  734. bRet = SetupGetStringField(&context, 1, szResetType, ARRAYSIZE(szResetType), NULL)
  735. && SetupGetStringField(&context, 2, szRegType, ARRAYSIZE(szRegType), NULL)
  736. && SetupGetStringField(&context, 3, szRegKey, ARRAYSIZE(szRegKey), NULL);
  737. if (bRet)
  738. {
  739. // Check if there is a registry key specified in Registry line or not
  740. if (szRegKey[0] != '\0')
  741. {
  742. *pbRegistryLineAvailable = TRUE;
  743. if (!Str2KeyPath(szRegKey, &hKey, &lpSubKeyPath))
  744. {
  745. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  746. goto EXIT;
  747. }
  748. if (hKeyRoot)
  749. {
  750. hKey = hKeyRoot;
  751. }
  752. dwResetType = _tcstoul(szResetType, &lpEnd, 10);
  753. switch (dwResetType)
  754. {
  755. //
  756. // Value Data reset
  757. //
  758. case 0:
  759. bRet = SetupGetStringField(&context,
  760. 4,
  761. szValueName,
  762. ARRAYSIZE(szValueName),
  763. NULL)
  764. && SetupGetStringField(&context,
  765. 5,
  766. szOldValue,
  767. ARRAYSIZE(szOldValue),
  768. NULL)
  769. && SetupGetStringField(&context,
  770. 6,
  771. szNewValue,
  772. ARRAYSIZE(szNewValue),
  773. NULL);
  774. if (!bRet)
  775. {
  776. hr = HRESULT_FROM_WIN32(GetLastError());
  777. DPF(dlError,
  778. TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
  779. context.Section,
  780. context.Line,
  781. hr);
  782. goto EXIT;
  783. }
  784. if (MyStrCmpI(szOldValue, TEXT("")) != LSTR_EQUAL)
  785. {
  786. cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof(TCHAR);
  787. lRet = RegGetValue(hKey,
  788. lpSubKeyPath,
  789. szValueName,
  790. &dwType,
  791. (LPBYTE) szValueInReg,
  792. &cbValueInReg);
  793. if (lRet != ERROR_SUCCESS)
  794. {
  795. hr = HRESULT_FROM_WIN32(lRet);
  796. if (lRet == ERROR_FILE_NOT_FOUND)
  797. {
  798. bNeedRegReset = FALSE;
  799. }
  800. goto EXIT;
  801. }
  802. dwRegType = _tcstoul(szRegType, &lpEnd, 10);
  803. switch (dwRegType)
  804. {
  805. case REG_SZ:
  806. case REG_EXPAND_SZ:
  807. if (g_bBeforeMig)
  808. {
  809. //If we run before upgrade, and the string in registry is not the
  810. //same as original one defined in INF file, that means user customized
  811. //that shell folder, we just simple return as success with failure
  812. if (MyStrCmpI(szValueInReg, szOldValue) != LSTR_EQUAL)
  813. {
  814. bNeedRegReset = FALSE;
  815. goto EXIT;
  816. }
  817. }
  818. else
  819. {
  820. //If we run after upgrade, and the string in registry is neither the
  821. //same as original one defined in INF file,nor the English string , that
  822. //means user customized that shell folder, we just simple return as
  823. //success with failure
  824. if (MyStrCmpI(szValueInReg, szOldValue) != LSTR_EQUAL
  825. && MyStrCmpI(szValueInReg, szNewValue) != LSTR_EQUAL)
  826. {
  827. bNeedRegReset = FALSE;
  828. goto EXIT;
  829. }
  830. }
  831. break;
  832. case REG_MULTI_SZ:
  833. if (g_bBeforeMig)
  834. {
  835. if (!MultiSzSubStr(szOldValue, szValueInReg))
  836. {
  837. bNeedRegReset = FALSE;
  838. goto EXIT;
  839. }
  840. }
  841. else
  842. {
  843. if (!MultiSzSubStr(szOldValue, szValueInReg)
  844. && !MultiSzSubStr(szNewValue, szValueInReg))
  845. {
  846. bNeedRegReset = FALSE;
  847. goto EXIT;
  848. }
  849. }
  850. break;
  851. }
  852. }
  853. break;
  854. //
  855. // Value Name reset
  856. //
  857. case 1:
  858. bRet = SetupGetStringField(&context,
  859. 4,
  860. szValueName,
  861. ARRAYSIZE(szValueName),
  862. NULL)
  863. && SetupGetStringField(&context,
  864. 5,
  865. szNewValueName,
  866. ARRAYSIZE(szNewValueName),
  867. NULL);
  868. if (!bRet)
  869. {
  870. hr = HRESULT_FROM_WIN32(GetLastError());
  871. DPF(dlError,
  872. TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
  873. context.Section,
  874. context.Line,
  875. hr);
  876. goto EXIT;
  877. }
  878. cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof(TCHAR);
  879. if (g_bBeforeMig)
  880. {
  881. lRet = RegGetValue(hKey,
  882. lpSubKeyPath,
  883. szValueName,
  884. &dwType,
  885. (LPBYTE) szValueInReg,
  886. &cbValueInReg);
  887. if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
  888. {
  889. bNeedRegReset = FALSE;
  890. goto EXIT;
  891. }
  892. }
  893. else
  894. {
  895. lRet = RegGetValue(hKey,
  896. lpSubKeyPath,
  897. szValueName,
  898. &dwType,
  899. (LPBYTE) szValueInReg,
  900. &cbValueInReg);
  901. if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
  902. {
  903. lRet = RegGetValue(hKey,
  904. lpSubKeyPath,
  905. szNewValueName,
  906. &dwType,
  907. (LPBYTE) szValueInReg,
  908. &cbValueInReg);
  909. if (lRet != ERROR_SUCCESS && lRet == ERROR_FILE_NOT_FOUND)
  910. {
  911. bNeedRegReset = FALSE;
  912. goto EXIT;
  913. }
  914. }
  915. }
  916. break;
  917. //
  918. // Registry Key reset
  919. //
  920. case 2:
  921. bRet = SetupGetStringField(&context,
  922. 4,
  923. szNewRegKeyName,
  924. ARRAYSIZE(szNewRegKeyName),
  925. NULL);
  926. if (!bRet)
  927. {
  928. hr = HRESULT_FROM_WIN32(GetLastError());
  929. DPF(dlError,
  930. TEXT("Get registry info failed in section[%s], line [%d] - hr = 0x%X"),
  931. context.Section,
  932. context.Line,
  933. hr);
  934. goto EXIT;
  935. }
  936. break;
  937. // Invalid type
  938. default:
  939. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  940. DPF(dlError,
  941. TEXT("Invalid Reset Type [%d], section [%s], line [%d]"),
  942. dwResetType,
  943. context.Section,
  944. context.Line);
  945. goto EXIT;
  946. }
  947. }
  948. }
  949. else
  950. {
  951. hr = HRESULT_FROM_WIN32(GetLastError());
  952. DPF(dlError,
  953. TEXT("Get registry info failed in section [%s], line [%d] - hr = 0x%X"),
  954. context.Section,
  955. context.Line,
  956. hr);
  957. goto EXIT;
  958. }
  959. bRet = SetupFindNextMatchLine(&context, SHELL_FOLDER_REGISTRY, &context);
  960. }
  961. EXIT:
  962. if (!bNeedRegReset)
  963. {
  964. hr = S_FALSE;
  965. }
  966. return hr;
  967. }
  968. HRESULT UpdateSystemRegistryWithRegistryLines(
  969. HKEY hKeyRoot,
  970. HINF hInf,
  971. LPCTSTR lpSection,
  972. LPCTSTR lpUserName
  973. )
  974. {
  975. HRESULT hr = S_OK;
  976. BOOL bRet;
  977. LONG lRet;
  978. HKEY hKey;
  979. TCHAR szResetType[4];
  980. TCHAR szRegType[4];
  981. TCHAR szRegKey[MAX_PATH];
  982. TCHAR szOldKeyName[MAX_PATH];
  983. TCHAR szNewKeyName[MAX_PATH];
  984. TCHAR szValueName[MAX_PATH];
  985. TCHAR szNewValueName[MAX_PATH];
  986. TCHAR szOldValue[512];
  987. TCHAR szNewValue[512];
  988. TCHAR szValueInReg[512];
  989. DWORD cbValueInReg;
  990. LPTSTR lpEnd;
  991. LPTSTR lpSubKeyPath = NULL;
  992. DWORD dwResetType;
  993. DWORD dwRegType;
  994. DWORD dwType;
  995. INFCONTEXT context;
  996. bRet = SetupFindFirstLine(hInf, lpSection, SHELL_FOLDER_REGISTRY, &context);
  997. while (bRet && SUCCEEDED(hr))
  998. {
  999. SetupGetStringField(&context, 1, szResetType, ARRAYSIZE(szResetType), NULL);
  1000. SetupGetStringField(&context, 2, szRegType, ARRAYSIZE(szRegType), NULL);
  1001. SetupGetStringField(&context, 3, szRegKey, ARRAYSIZE(szRegKey), NULL);
  1002. dwResetType = _tcstoul(szResetType, &lpEnd, 10);
  1003. dwRegType = _tcstoul(szRegType, &lpEnd, 10);
  1004. switch (dwResetType)
  1005. {
  1006. case 0:
  1007. SetupGetStringField(&context, 4, szValueName, ARRAYSIZE(szValueName), NULL);
  1008. SetupGetStringField(&context, 5, szOldValue, ARRAYSIZE(szOldValue), NULL);
  1009. SetupGetStringField(&context, 6, szNewValue, ARRAYSIZE(szNewValue), NULL);
  1010. if (dwRegType == REG_MULTI_SZ)
  1011. {
  1012. if (!Str2KeyPath(szRegKey, &hKey, &lpSubKeyPath))
  1013. {
  1014. goto EXIT;
  1015. }
  1016. if (hKeyRoot)
  1017. {
  1018. hKey = hKeyRoot;
  1019. }
  1020. cbValueInReg = ARRAYSIZE(szValueInReg) * sizeof (TCHAR);
  1021. lRet = RegGetValue(hKey,
  1022. lpSubKeyPath,
  1023. szValueName,
  1024. &dwType,
  1025. (LPBYTE) szValueInReg,
  1026. &cbValueInReg);
  1027. if (lRet == ERROR_SUCCESS)
  1028. {
  1029. TCHAR szNewMultiSz[MAX_PATH];
  1030. DWORD cchNewMultiSz;
  1031. LPCTSTR lpNextSz;
  1032. LPTSTR lpStart;
  1033. LPTSTR lpMultiSz;
  1034. szNewMultiSz[0] = TEXT('\0');
  1035. szNewMultiSz[1] = TEXT('\0');
  1036. cchNewMultiSz = ARRAYSIZE(szNewMultiSz);
  1037. lpMultiSz = szNewMultiSz;
  1038. lpNextSz = MultiSzTok(szValueInReg);
  1039. while (lpNextSz != NULL)
  1040. {
  1041. lpStart = StrStrI(lpNextSz, szOldValue);
  1042. if (lpStart)
  1043. {
  1044. TCHAR szTemp[MAX_PATH];
  1045. INT nStartReplace;
  1046. nStartReplace = (INT) (lpStart - lpNextSz);
  1047. lstrcpyn(szTemp,
  1048. lpNextSz,
  1049. nStartReplace + 1);
  1050. hr = StringCchCat(szTemp,
  1051. ARRAYSIZE(szTemp),
  1052. szNewValue);
  1053. if (FAILED(hr))
  1054. {
  1055. goto EXIT;
  1056. }
  1057. nStartReplace += lstrlen(szOldValue);
  1058. hr = StringCchCat(szTemp,
  1059. ARRAYSIZE(szTemp),
  1060. (lpNextSz + nStartReplace));
  1061. if (FAILED(hr))
  1062. {
  1063. goto EXIT;
  1064. }
  1065. AppendSzToMultiSz(szTemp,
  1066. &lpMultiSz,
  1067. &cchNewMultiSz);
  1068. }
  1069. else
  1070. {
  1071. AppendSzToMultiSz(lpNextSz,
  1072. &lpMultiSz,
  1073. &cchNewMultiSz);
  1074. }
  1075. lpNextSz = MultiSzTok(NULL);
  1076. }
  1077. hr = AddRegValueRename(szRegKey,
  1078. szValueName,
  1079. NULL,
  1080. szValueInReg,
  1081. szNewMultiSz,
  1082. dwRegType,
  1083. 0,
  1084. (LPTSTR) lpUserName);
  1085. }
  1086. }
  1087. else
  1088. {
  1089. hr = AddRegValueRename(szRegKey,
  1090. szValueName,
  1091. NULL,
  1092. szOldValue,
  1093. szNewValue,
  1094. dwRegType,
  1095. 0,
  1096. (LPTSTR) lpUserName);
  1097. }
  1098. break;
  1099. case 1:
  1100. SetupGetStringField(&context, 4, szValueName, ARRAYSIZE(szValueName), NULL);
  1101. SetupGetStringField(&context, 5, szNewValueName, ARRAYSIZE(szNewValueName), NULL);
  1102. hr = AddRegValueRename(szRegKey,
  1103. szValueName,
  1104. szNewValueName,
  1105. NULL,
  1106. NULL,
  1107. dwRegType,
  1108. 0,
  1109. (LPTSTR) lpUserName);
  1110. break;
  1111. case 2:
  1112. SetupGetStringField(&context, 4, szOldKeyName, ARRAYSIZE(szOldKeyName), NULL);
  1113. SetupGetStringField(&context, 5, szNewKeyName, ARRAYSIZE(szNewKeyName), NULL);
  1114. hr = AddRegKeyRename(szRegKey,
  1115. szOldKeyName,
  1116. szNewKeyName,
  1117. (LPTSTR) lpUserName);
  1118. break;
  1119. }
  1120. bRet = SetupFindNextMatchLine(&context, SHELL_FOLDER_REGISTRY, &context);
  1121. }
  1122. EXIT:
  1123. return hr;
  1124. }
  1125. HRESULT CheckAndAddHardLinkLine(
  1126. HINF hInf,
  1127. LPCTSTR lpSection,
  1128. LPTSTR lpUser
  1129. )
  1130. {
  1131. HRESULT hr = S_OK;
  1132. INFCONTEXT context;
  1133. TCHAR szType[10],szLinkValue[MAX_PATH+1],szLinkName[MAX_PATH+1];
  1134. if (!SetupFindFirstLine(hInf, lpSection, TEXT("HardLink"), &context))
  1135. {
  1136. hr = S_FALSE;
  1137. goto Cleanup;
  1138. }
  1139. if (!SetupGetStringField(&context,1,szType,ARRAYSIZE(szType),NULL)
  1140. || !SetupGetStringField(&context,2,szLinkName,ARRAYSIZE(szLinkName),NULL)
  1141. || !SetupGetStringField(&context,3,szLinkValue,ARRAYSIZE(szLinkValue),NULL))
  1142. {
  1143. DWORD dw = GetLastError();
  1144. hr = HRESULT_FROM_WIN32(dw);
  1145. DPF(dlError,TEXT("get Hardlink info failed in [%n],line %n with %n !"),context.Section ,context.Line,dw);
  1146. goto Cleanup;
  1147. }
  1148. if (!lpUser || !MyStrCmpI(lpUser,TEXT("System")) || !MyStrCmpI(lpUser,DEFAULT_USER))
  1149. {
  1150. hr = AddHardLinkEntry(szLinkName, szLinkValue, szType, lpUser, NULL, NULL);
  1151. }
  1152. Cleanup:
  1153. return hr;
  1154. }