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.

8892 lines
253 KiB

  1. //-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: utils.c
  7. //
  8. // Contents: Cross Language Migration Tools utility function
  9. //
  10. // History: 09/17/2001 Xiaofeng Zang (xiaoz) Created
  11. //
  12. // Notes:
  13. //
  14. //-----------------------------------------------------------------------
  15. #include "StdAfx.h"
  16. #include "clmt.h"
  17. #include <esent97.h>
  18. #include <dsrole.h>
  19. #include <Ntdsapi.h>
  20. HRESULT MakeDOInfCopy();
  21. //-----------------------------------------------------------------------
  22. //
  23. // Function: ConcatenatePaths
  24. //
  25. // Descrip: Concat the 2 paths into 1 into Target
  26. //
  27. // Returns: BOOL
  28. //
  29. // Notes: none
  30. //
  31. // History: 09/17/2001 xiaoz created
  32. //
  33. // Notes: if buffer is small to hold the concated string, return value
  34. // will be false,however, the truncated string still got copied
  35. //
  36. //-----------------------------------------------------------------------
  37. BOOL
  38. ConcatenatePaths(
  39. LPTSTR Target,
  40. LPCTSTR Path,
  41. UINT TargetBufferSize )
  42. {
  43. UINT TargetLength,PathLength;
  44. BOOL TrailingBackslash,LeadingBackslash;
  45. UINT EndingLength;
  46. TargetLength = lstrlen(Target);
  47. PathLength = lstrlen(Path);
  48. //
  49. // See whether the target has a trailing backslash.
  50. //
  51. if(TargetLength && (Target[TargetLength-1] == TEXT('\\')))
  52. {
  53. TrailingBackslash = TRUE;
  54. TargetLength--;
  55. }
  56. else
  57. {
  58. TrailingBackslash = FALSE;
  59. }
  60. //
  61. // See whether the path has a leading backshash.
  62. //
  63. if(Path[0] == TEXT('\\'))
  64. {
  65. LeadingBackslash = TRUE;
  66. PathLength--;
  67. }
  68. else
  69. {
  70. LeadingBackslash = FALSE;
  71. }
  72. //
  73. // Calculate the ending length, which is equal to the sum of
  74. // the length of the two strings modulo leading/trailing
  75. // backslashes, plus one path separator, plus a nul.
  76. //
  77. EndingLength = TargetLength + PathLength + 2;
  78. if(!LeadingBackslash && (TargetLength < TargetBufferSize))
  79. {
  80. Target[TargetLength++] = TEXT('\\');
  81. }
  82. if(TargetBufferSize > TargetLength)
  83. {
  84. lstrcpyn(Target+TargetLength,Path,TargetBufferSize-TargetLength);
  85. }
  86. //
  87. // Make sure the buffer is nul terminated in all cases.
  88. //
  89. if (TargetBufferSize)
  90. {
  91. Target[TargetBufferSize-1] = 0;
  92. }
  93. return(EndingLength <= TargetBufferSize);
  94. }
  95. //-----------------------------------------------------------------------
  96. //
  97. // Function: StrToUInt
  98. //
  99. // Descrip:
  100. //
  101. // Returns: UINT
  102. //
  103. // Notes: none
  104. //
  105. // History: 09/17/2001 xiaoz created
  106. //
  107. // Notes: none
  108. //
  109. //-----------------------------------------------------------------------
  110. UINT StrToUInt(
  111. LPTSTR lpszNum)
  112. {
  113. LPTSTR lpszStop;
  114. #ifdef UNICODE
  115. return (wcstoul(lpszNum, &lpszStop, 16));
  116. #else
  117. return (strtoul(lpszNum, &lpszStop, 16));
  118. #endif
  119. }
  120. //-----------------------------------------------------------------------
  121. //
  122. // Function: INIFile_ChangeSectionName
  123. //
  124. // Descrip: change a section name in the INF file
  125. //
  126. // Returns: BOOL
  127. //
  128. // Notes: none
  129. //
  130. // History: 09/17/2001 xiaoz created
  131. //
  132. // Notes: none
  133. //
  134. //-----------------------------------------------------------------------
  135. BOOL INIFile_ChangeSectionName(
  136. LPCTSTR szIniFileName,
  137. LPCTSTR szIniOldSectionName,
  138. LPCTSTR szIniNewSectionName)
  139. {
  140. LPTSTR pBuf = NULL;
  141. BOOL bRetVal = FALSE;
  142. DWORD ccbBufsize = 0x7FFFF;
  143. DWORD copied_chars;
  144. DPF (INFmsg ,TEXT("[INIFile_ChangeSectionName] Calling ,%s,%s,%s !"),
  145. szIniFileName,szIniOldSectionName,szIniNewSectionName);
  146. //
  147. // allocate max size of buffer
  148. //
  149. do
  150. {
  151. if (pBuf)
  152. {
  153. free(pBuf);
  154. ccbBufsize *= 2;
  155. }
  156. pBuf = (LPTSTR) malloc(ccbBufsize * sizeof(TCHAR));
  157. if (!pBuf)
  158. {
  159. DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !"));
  160. goto Exit1;
  161. }
  162. copied_chars = GetPrivateProfileSection(szIniOldSectionName,
  163. pBuf,
  164. ccbBufsize,
  165. szIniFileName);
  166. } while (copied_chars == ccbBufsize -2);
  167. if (! copied_chars)
  168. {
  169. //
  170. // this section is not in INI file
  171. //
  172. // do nothing
  173. //
  174. DPF (INFerr,TEXT("[INIFile_ChangeSectionName] No %s section in %s !"),szIniOldSectionName);
  175. goto Exit2;
  176. }
  177. bRetVal = WritePrivateProfileSection(
  178. szIniNewSectionName,
  179. pBuf,
  180. szIniFileName);
  181. if (! bRetVal)
  182. {
  183. //
  184. // write failure
  185. //
  186. DPF (dlError,TEXT("[INIFile_ChangeSectionName] WritePrivateProfileSection fail!"));
  187. goto Exit2;
  188. }
  189. //Delete the old section
  190. WritePrivateProfileSection(
  191. szIniOldSectionName,
  192. NULL,
  193. szIniFileName);
  194. //
  195. // at this step, even old section is not deleted, it's still OK
  196. //
  197. bRetVal = TRUE;
  198. Exit2:
  199. if (pBuf)
  200. {
  201. free(pBuf);
  202. }
  203. Exit1:
  204. return bRetVal;
  205. }
  206. //-----------------------------------------------------------------------
  207. //
  208. // Function: INIFile_ChangeSectionName
  209. //
  210. // Descrip: change a section name in the INF file
  211. //
  212. // Returns: BOOL
  213. //
  214. // Notes: none
  215. //
  216. // History: 09/17/2001 xiaoz created
  217. //
  218. // Notes: none
  219. //
  220. //-----------------------------------------------------------------------
  221. BOOL INIFile_Merge2Section(
  222. LPCTSTR szIniFileName,
  223. LPCTSTR szSourceSection,
  224. LPCTSTR szDestSection)
  225. {
  226. LPTSTR pBufSource = NULL, pBufDest = NULL, pBufMerged = NULL;
  227. BOOL bRetVal = FALSE;
  228. DWORD cchBufsize;
  229. DWORD srccopied_chars, dstcopied_chars;
  230. DPF (INFmsg ,TEXT("[INIFile_Merger2Section] Calling ,%s,%s,%s !"),
  231. szIniFileName,szSourceSection,szDestSection);
  232. //
  233. // allocate max size of buffer
  234. //
  235. cchBufsize = 0x7FFFF;
  236. do
  237. {
  238. if (pBufDest)
  239. {
  240. free(pBufDest);
  241. cchBufsize *= 2;
  242. }
  243. pBufDest = (LPTSTR) malloc(cchBufsize * sizeof(TCHAR));
  244. if (!pBufDest)
  245. {
  246. DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !"));
  247. goto Exit;
  248. }
  249. dstcopied_chars = GetPrivateProfileSection(szDestSection,
  250. pBufDest,
  251. cchBufsize,
  252. szIniFileName);
  253. } while (dstcopied_chars == cchBufsize -2);
  254. if (! dstcopied_chars)
  255. {
  256. //
  257. // this section is not in INI file
  258. //
  259. // do nothing
  260. //
  261. DPF (INFerr,TEXT("[INIFile_Merger2Section] No %s section in %s !"),szDestSection);
  262. goto Exit;
  263. }
  264. cchBufsize = 0x7FFFF;
  265. do
  266. {
  267. if (pBufSource)
  268. {
  269. free(pBufSource);
  270. cchBufsize *= 2;
  271. }
  272. pBufSource = (LPTSTR) malloc(cchBufsize * sizeof(TCHAR));
  273. if (!pBufSource)
  274. {
  275. DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !"));
  276. goto Exit;
  277. }
  278. srccopied_chars = GetPrivateProfileSection(szSourceSection,
  279. pBufSource,
  280. cchBufsize,
  281. szIniFileName);
  282. } while (srccopied_chars == cchBufsize -2);
  283. if (! srccopied_chars)
  284. {
  285. //
  286. // this section is not in INI file
  287. //
  288. // do nothing
  289. //
  290. DPF (INFerr,TEXT("[INIFile_Merger2Section] No %s section in %s !"),szSourceSection);
  291. goto Exit;
  292. }
  293. pBufMerged = (LPTSTR) malloc((srccopied_chars + dstcopied_chars + 1) * sizeof(TCHAR));
  294. if (!pBufMerged)
  295. {
  296. DPF (INFerr,TEXT("[INIFile_ChangeSectionName] memory allocate error !"));
  297. goto Exit;
  298. }
  299. memmove((LPBYTE)pBufMerged,(LPBYTE)pBufDest,dstcopied_chars * sizeof(TCHAR));
  300. memmove((LPBYTE)(pBufMerged + dstcopied_chars),(LPBYTE)pBufSource,srccopied_chars * sizeof(TCHAR));
  301. pBufMerged[srccopied_chars + dstcopied_chars] = TEXT('\0');
  302. bRetVal = WritePrivateProfileSection(
  303. szDestSection,
  304. pBufMerged,
  305. szIniFileName);
  306. if (! bRetVal)
  307. {
  308. //
  309. // write failure
  310. //
  311. DPF (dlError,TEXT("[INIFile_ChangeSectionName] WritePrivateProfileSection fail!"));
  312. goto Exit;
  313. }
  314. bRetVal = TRUE;
  315. Exit:
  316. FreePointer(pBufSource);
  317. FreePointer(pBufDest);
  318. FreePointer(pBufMerged);
  319. return bRetVal;
  320. }
  321. //-----------------------------------------------------------------------------
  322. //
  323. // Function: INIFile_IsSectionExist
  324. //
  325. // Synopsis: Find out whether the section name is existed in INF file or not
  326. //
  327. // Returns: TRUE if found, FALSE otherwise
  328. //
  329. // History: 02/07/2002 Rerkboos Created
  330. //
  331. // Notes: None.
  332. //
  333. //-----------------------------------------------------------------------------
  334. BOOL INIFile_IsSectionExist(
  335. LPCTSTR lpSection, // Section name to be searched
  336. LPCTSTR lpINFFile // INF file name
  337. )
  338. {
  339. HINF hInf;
  340. BOOL fRet = FALSE;
  341. if (NULL == lpSection || NULL == lpINFFile)
  342. {
  343. return FALSE;
  344. }
  345. hInf = SetupOpenInfFile(lpINFFile, NULL, INF_STYLE_WIN4, NULL);
  346. if (INVALID_HANDLE_VALUE != hInf)
  347. {
  348. if (SetupGetLineCount(hInf, lpSection) > 0)
  349. {
  350. fRet = TRUE;
  351. }
  352. SetupCloseInfFile(hInf);
  353. }
  354. return fRet;
  355. }
  356. //-----------------------------------------------------------------------
  357. //
  358. // Function: IntToString
  359. //
  360. // Descrip:
  361. //
  362. // Returns: void
  363. //
  364. // Notes: none
  365. //
  366. // History: 09/17/2001 xiaoz created
  367. //
  368. // Notes: none
  369. //
  370. //-----------------------------------------------------------------------
  371. void IntToString(
  372. DWORD i,
  373. LPTSTR sz)
  374. {
  375. #define CCH_MAX_DEC 12 // Number of chars needed to hold 2^32
  376. TCHAR szTemp[CCH_MAX_DEC];
  377. int iChr;
  378. iChr = 0;
  379. do {
  380. szTemp[iChr++] = TEXT('0') + (TCHAR)(i % 10);
  381. i = i / 10;
  382. } while (i != 0);
  383. do {
  384. iChr--;
  385. *sz++ = szTemp[iChr];
  386. } while (iChr != 0);
  387. *sz++ = TEXT('\0');
  388. }
  389. //-----------------------------------------------------------------------
  390. //
  391. // Function: IsDirExisting
  392. //
  393. // Descrip: Check whether the Dir exists or not
  394. //
  395. // Returns: BOOL
  396. //
  397. // Notes:
  398. //
  399. // History: 09/17/2001 xiaoz created
  400. //
  401. // Notes: none
  402. //
  403. //-----------------------------------------------------------------------
  404. BOOL IsDirExisting(LPTSTR Dir)
  405. {
  406. LONG lResult = GetFileAttributes(Dir);
  407. DPF (dlInfo,TEXT("[IsDirExisting] %s lResult:%X"),Dir,lResult);
  408. if ((lResult == 0xFFFFFFFF) ||
  409. (!(lResult & FILE_ATTRIBUTE_DIRECTORY)))
  410. {
  411. return FALSE;
  412. }
  413. else
  414. {
  415. return TRUE;
  416. }
  417. }
  418. LONG IsDirExisting2(LPTSTR Dir, PBOOL pbExit)
  419. {
  420. LONG lResult = GetFileAttributes(Dir);
  421. DPF (dlInfo,TEXT("[IsDirExisting] %s lResult:%X"),Dir,lResult);
  422. if (lResult == INVALID_FILE_ATTRIBUTES)
  423. {
  424. DWORD dwErr = GetLastError();
  425. if ( (dwErr == ERROR_FILE_NOT_FOUND)
  426. || (dwErr == ERROR_PATH_NOT_FOUND) )
  427. {
  428. *pbExit = FALSE;
  429. return ERROR_SUCCESS;
  430. }
  431. else
  432. {
  433. return dwErr;
  434. }
  435. }
  436. else
  437. {
  438. *pbExit = TRUE;
  439. return ERROR_SUCCESS;
  440. }
  441. }
  442. //-----------------------------------------------------------------------
  443. //
  444. // Function: IsFileFolderExisting
  445. //
  446. // Descrip: Check whether the File exists or not
  447. //
  448. // Returns: BOOL
  449. //
  450. // Notes:
  451. //
  452. // History: 09/17/2001 xiaoz created
  453. //
  454. // Notes: none
  455. //
  456. //-----------------------------------------------------------------------
  457. BOOL IsFileFolderExisting( LPTSTR File)
  458. {
  459. LONG lResult = GetFileAttributes(File);
  460. DPF (dlInfo,TEXT("[IsFileFolderExisting] %s lResult:%X"),File,lResult);
  461. if (lResult == 0xFFFFFFFF)
  462. {
  463. return FALSE;
  464. }
  465. else
  466. {
  467. return TRUE;
  468. }
  469. }
  470. //-----------------------------------------------------------------------
  471. //
  472. // Function: MyMoveFile
  473. //
  474. // Descrip: Rename a file or direcory
  475. //
  476. // Returns: HRESULT
  477. //
  478. // Notes:
  479. //
  480. // History: 09/17/2001 xiaoz created
  481. //
  482. // Notes: none
  483. //
  484. //-----------------------------------------------------------------------
  485. HRESULT MyMoveFile(
  486. LPCTSTR lpExistingFileName, // file name
  487. LPCTSTR lpNewFileName, // new file name
  488. BOOL bAnalyze, // if it's analyze mode, it will add an entry in INF file
  489. // for future renaming
  490. BOOL bIsFileProtected)
  491. {
  492. LPCTSTR lpMyNewFileName = lpNewFileName;
  493. if (!lpExistingFileName)
  494. {
  495. return E_INVALIDARG;
  496. }
  497. if (!IsFileFolderExisting((LPTSTR)lpExistingFileName))
  498. {
  499. return S_FALSE;
  500. }
  501. if (!MyStrCmpI(lpExistingFileName,lpNewFileName))
  502. {
  503. return S_FALSE;
  504. }
  505. if (!lpNewFileName || !lpNewFileName[0])
  506. {
  507. lpMyNewFileName = NULL;
  508. }
  509. if (bAnalyze)
  510. {
  511. HRESULT hr;
  512. DWORD dwType;
  513. if (bIsFileProtected)
  514. {
  515. dwType = TYPE_SFPFILE_MOVE;
  516. }
  517. else
  518. {
  519. dwType = TYPE_FILE_MOVE;
  520. }
  521. return (AddFolderRename((LPTSTR)lpExistingFileName,(LPTSTR)lpMyNewFileName,dwType,NULL));
  522. }
  523. else
  524. {
  525. if (MoveFileEx(lpExistingFileName,lpMyNewFileName,MOVEFILE_DELAY_UNTIL_REBOOT))
  526. {
  527. return S_OK;
  528. }
  529. else
  530. {
  531. return HRESULT_FROM_WIN32(GetLastError());
  532. }
  533. }
  534. }
  535. //-----------------------------------------------------------------------
  536. //
  537. // Function: AddHardLinkEntry
  538. //
  539. // Descrip: add an entry in hardlink section
  540. //
  541. // Returns: HRESULT
  542. //
  543. // Notes:
  544. //
  545. // History: 04/10/2002 xiaoz created
  546. //
  547. // Notes: none
  548. //
  549. //-----------------------------------------------------------------------
  550. HRESULT AddHardLinkEntry(
  551. LPTSTR szLinkName, //Link Name to created
  552. LPTSTR szLinkValue, //the name you want to link to
  553. LPTSTR szType,
  554. LPTSTR lpUser,
  555. LPTSTR lpHiddenType,
  556. LPTSTR lpKeyname
  557. )
  558. {
  559. LPTSTR lpszSectionName;
  560. LPTSTR szOneLine = NULL;
  561. size_t CchOneLine = MAX_PATH;
  562. TCHAR szIndex[MAX_PATH];
  563. LPTSTR lpCurrIndex = szIndex;
  564. HRESULT hr;
  565. if (!szLinkName ||!szLinkValue || !szType || !szLinkName[0] || !szLinkValue[0] || !szType[0])
  566. {
  567. hr = E_INVALIDARG;
  568. goto Cleanup;
  569. }
  570. CchOneLine += lstrlen(szLinkName)+lstrlen(szLinkValue) +lstrlen(szType);
  571. szOneLine = malloc(CchOneLine * sizeof(TCHAR));
  572. if (!szOneLine)
  573. {
  574. hr = E_OUTOFMEMORY;
  575. goto Cleanup;
  576. }
  577. if (!lpHiddenType)
  578. {
  579. hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%s,\"%s\",\"%s\""),
  580. szType,szLinkName,szLinkValue);
  581. }
  582. else
  583. {
  584. hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%s,\"%s\",\"%s\",\"%s\""),
  585. szType,szLinkName,szLinkValue,lpHiddenType);
  586. }
  587. if (FAILED(hr))
  588. {
  589. goto Cleanup;
  590. }
  591. if (lpKeyname && (g_dwKeyIndex < 0xFFFF))
  592. {
  593. g_dwKeyIndex = 0xFFFF;
  594. _itot(g_dwKeyIndex,szIndex,16);
  595. }
  596. else
  597. {
  598. g_dwKeyIndex++;
  599. _itot(g_dwKeyIndex,szIndex,16);
  600. }
  601. if (lpUser && !MyStrCmpI(lpUser,DEFAULT_USER))
  602. {
  603. lpszSectionName = TEXT("Folder.HardLink.Peruser");
  604. }
  605. else
  606. {
  607. lpszSectionName = TEXT("Folder.HardLink");
  608. }
  609. if (!WritePrivateProfileString(lpszSectionName,lpCurrIndex,szOneLine,g_szToDoINFFileName))
  610. {
  611. hr = HRESULT_FROM_WIN32(GetLastError());
  612. goto Cleanup;
  613. }
  614. hr = S_OK;
  615. Cleanup:
  616. if (szOneLine)
  617. {
  618. free(szOneLine);
  619. }
  620. return hr;
  621. }
  622. //-----------------------------------------------------------------------
  623. //
  624. // Function: MyMoveDirectory
  625. //
  626. // Descrip: Rename SourceDir to DestDir
  627. //
  628. // Returns: BOOL
  629. //
  630. // Notes:
  631. //
  632. // History: 09/17/2001 xiaoz created
  633. //
  634. // Notes: if the directory is in use, a deferred move will be
  635. // performed and we set the system reboot statue
  636. // MoveFileEx will fail for directory when DestDir is
  637. // already exitsing
  638. // if bTakeCareBackupDir is TRUE, this function will make
  639. // a backup for DestDir if it exists.
  640. //-----------------------------------------------------------------------
  641. HRESULT MyMoveDirectory(
  642. LPTSTR SourceDir,
  643. LPTSTR DestDir,
  644. BOOL bTakeCareBackupDir,
  645. BOOL bAnalyze,
  646. BOOL bCreateHardLink,
  647. DWORD dwShellID)
  648. {
  649. HRESULT hr;
  650. size_t cChSourceDir, cChDestDir ;
  651. LPTSTR lpSourceBackupDir, lpDestBackupDir;
  652. BOOL bDirExist;
  653. DWORD dwStatus;
  654. lpSourceBackupDir = lpDestBackupDir = NULL;
  655. dwStatus = IsDirExisting2(SourceDir,&bDirExist);
  656. if (ERROR_SUCCESS == dwStatus)
  657. {
  658. if (!bDirExist)
  659. {
  660. hr = S_FALSE;
  661. goto Cleanup;
  662. }
  663. }
  664. else
  665. {
  666. hr = HRESULT_FROM_WIN32(dwStatus);
  667. DPF(APPerr, TEXT("Error: current user maybe can not access folder %s "),SourceDir);
  668. goto Cleanup;
  669. }
  670. if (!MyStrCmpI(SourceDir,DestDir))
  671. {
  672. hr = S_FALSE;
  673. goto Cleanup;
  674. }
  675. if (bAnalyze)
  676. {
  677. BOOL bAccess;
  678. LPTSTR lp = StrRChrI(SourceDir,NULL,TEXT('\\'));
  679. TCHAR cCh;
  680. if (!lp)
  681. {
  682. hr = S_FALSE;
  683. goto Cleanup;
  684. }
  685. //Try self first
  686. hr = IsObjectAccessiablebyLocalSys(SourceDir,SE_FILE_OBJECT,&bAccess);
  687. if (hr != S_OK)
  688. {
  689. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  690. DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir);
  691. goto Cleanup;
  692. }
  693. //try parent
  694. if (*(lp-1) == TEXT(':'))
  695. {
  696. lp++;
  697. }
  698. cCh = *lp;
  699. *lp = TEXT('\0');
  700. hr = IsObjectAccessiablebyLocalSys(SourceDir,SE_FILE_OBJECT,&bAccess);
  701. if (hr != S_OK)
  702. {
  703. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  704. DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir);
  705. goto Cleanup;
  706. }
  707. if (!bAccess)
  708. {
  709. DPF(APPerr, TEXT("Error: LocalSystem or Local Administartors Group or Anyone can not access folder %s "),SourceDir);
  710. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  711. goto Cleanup;
  712. }
  713. *lp = cCh;
  714. if (bTakeCareBackupDir && IsDirExisting(DestDir))
  715. {
  716. LPTSTR lpOld,lpNew,lpLastSlash;
  717. //
  718. // RERKBOOS: Add more code here...
  719. // We merge the content from Backup English folder to localized folder
  720. // then we will rename localized folder to English folder
  721. //
  722. #ifdef NEVER
  723. //Testing team decides to change mind and better not to add this code
  724. //we will just follow here
  725. hr = MergeDirectory(DestDir, SourceDir);
  726. if (FAILED(hr))
  727. {
  728. goto Cleanup;
  729. }
  730. #endif
  731. //We need to make sure DestDir does not exist
  732. cChDestDir = lstrlen(DestDir)+ MAX_PATH;
  733. lpDestBackupDir = malloc(cChDestDir * sizeof(TCHAR));
  734. if (!lpDestBackupDir)
  735. {
  736. hr = E_OUTOFMEMORY;
  737. goto Cleanup;
  738. }
  739. if (!GetBackupDir( DestDir,lpDestBackupDir,cChDestDir,FALSE))
  740. {
  741. hr = E_FAIL;
  742. goto Cleanup;
  743. }
  744. if (FAILED(hr = AddFolderRename(DestDir,lpDestBackupDir,TYPE_DIR_MOVE,NULL)))
  745. {
  746. goto Cleanup;
  747. }
  748. lpOld = StrRChrI(DestDir,NULL,TEXT('\\'));
  749. lpNew = StrRChrI(lpDestBackupDir,NULL,TEXT('\\'));
  750. lpLastSlash = lpOld;
  751. if (lpOld && lpNew)
  752. {
  753. lpOld++;
  754. lpNew++;
  755. //*lpLastSlash = TEXT('\0');
  756. if (!AddItemToStrRepaceTable(TEXT("SYSTEM"),lpOld,lpNew,DestDir,
  757. dwShellID,&g_StrReplaceTable))
  758. {
  759. hr = E_OUTOFMEMORY;
  760. goto Cleanup;
  761. }
  762. //*lpLastSlash = TEXT('\\');
  763. }
  764. }
  765. else
  766. {
  767. //We need to make sure DestDir does not exist
  768. cChDestDir = lstrlen(DestDir)+ MAX_PATH;
  769. lpDestBackupDir = malloc(cChDestDir * sizeof(TCHAR));
  770. if (lpDestBackupDir)
  771. {
  772. if (GetBackupDir( DestDir,lpDestBackupDir,cChDestDir,FALSE))
  773. {
  774. AddFolderRename(DestDir,lpDestBackupDir,TYPE_DIR_MOVE,NULL);
  775. }
  776. }
  777. }
  778. }
  779. //if we are here we are safe to move source dir to destination
  780. if (bAnalyze)
  781. {
  782. if (FAILED(hr = AddFolderRename(SourceDir,DestDir,TYPE_DIR_MOVE,NULL)))
  783. {
  784. goto Cleanup;
  785. }
  786. /*if (bCreateHardLink)
  787. {
  788. if (FAILED(hr = AddHardLinkEntry(SourceDir,DestDir)))
  789. {
  790. goto Cleanup;
  791. }
  792. }*/
  793. }
  794. else
  795. {
  796. if (!MoveFileEx(SourceDir,DestDir,MOVEFILE_DELAY_UNTIL_REBOOT))
  797. {
  798. hr = HRESULT_FROM_WIN32(GetLastError());
  799. goto Cleanup;
  800. }
  801. }
  802. if (bAnalyze && bTakeCareBackupDir)
  803. {
  804. cChSourceDir = lstrlen(SourceDir)+ MAX_PATH;
  805. lpSourceBackupDir = malloc(cChSourceDir * sizeof(TCHAR));
  806. if (!lpSourceBackupDir)
  807. {
  808. hr = E_OUTOFMEMORY;
  809. goto Cleanup;
  810. }
  811. if (GetBackupDir( SourceDir,lpSourceBackupDir,cChSourceDir,TRUE))
  812. {
  813. LPTSTR lpOld,lpNew,lpLastSlash;
  814. if (FAILED(hr = AddFolderRename(lpSourceBackupDir,SourceDir,TYPE_DIR_MOVE,NULL)))
  815. {
  816. goto Cleanup;
  817. }
  818. lpOld = StrRChrI(lpSourceBackupDir,NULL,TEXT('\\'));
  819. lpNew = StrRChrI(SourceDir,NULL,TEXT('\\'));
  820. lpLastSlash = lpOld;
  821. if (lpOld && lpNew)
  822. {
  823. lpOld++;
  824. lpNew++;
  825. //*lpLastSlash = TEXT('\0');
  826. if (!AddItemToStrRepaceTable(TEXT("SYSTEM"),lpOld,lpNew,lpSourceBackupDir,
  827. dwShellID,&g_StrReplaceTable))
  828. {
  829. hr = E_OUTOFMEMORY;
  830. goto Cleanup;
  831. }
  832. //*lpLastSlash = TEXT('\\');
  833. }
  834. }
  835. }
  836. hr = S_OK;
  837. Cleanup:
  838. FreePointer(lpSourceBackupDir);
  839. FreePointer(lpDestBackupDir);
  840. return hr;
  841. }
  842. //-----------------------------------------------------------------------
  843. //
  844. // Function: UpdateINFFileSys
  845. //
  846. // Descrip: adding ALLUSERSPROFILE/HOMEDRIVE/WINDIR Key in [String] section
  847. //
  848. // Returns: BOOL
  849. //
  850. // Notes:
  851. //
  852. // History: 09/17/2001 xiaoz created
  853. // 03/05/2002 rerkboos modified
  854. //
  855. // Notes:
  856. //
  857. //-----------------------------------------------------------------------
  858. HRESULT UpdateINFFileSys(
  859. LPTSTR lpInfFile
  860. )
  861. {
  862. HRESULT hr = E_FAIL;
  863. DWORD dwSize;
  864. TCHAR szStringSection[32];
  865. TCHAR szProfileDir[MAX_PATH];
  866. TCHAR szWindir[MAX_PATH+1];
  867. TCHAR szHomeDrive[MAX_PATH];
  868. TCHAR szSystemDrive[MAX_PATH];
  869. TCHAR szStr[MAX_PATH];
  870. TCHAR szComputerName[16];
  871. TCHAR szBackupDir[MAX_PATH];
  872. TCHAR szFirstNTFSDrive[4];
  873. INT i;
  874. struct _EnvPair
  875. {
  876. LPCTSTR lpEnvVarName;
  877. LPCTSTR lpValue;
  878. };
  879. struct _EnvPair epCLMT[] = {
  880. TEXT("ALLUSERSPROFILE"), szProfileDir,
  881. TEXT("HOMEDRIVE"), szHomeDrive,
  882. TEXT("WINDIR"), szWindir,
  883. TEXT("SYSTEMDRIVE"), szSystemDrive,
  884. TEXT("COMPUTERNAME"), szComputerName,
  885. TEXT("MUIBACKUPDIR"), szBackupDir,
  886. TEXT("FIRSTNTFSDRIVE"), szFirstNTFSDrive,
  887. NULL, NULL
  888. };
  889. if (lpInfFile == NULL)
  890. {
  891. return E_INVALIDARG;
  892. }
  893. DPF(APPmsg, TEXT("Enter UpdateINFFileSys:"));
  894. //
  895. // Get neccessary environment variables from system
  896. //
  897. dwSize = ARRAYSIZE(szProfileDir);
  898. if (!GetAllUsersProfileDirectory(szProfileDir, &dwSize))
  899. {
  900. DPF(APPerr, TEXT("Failed to get ALLUSERPROFILE"));
  901. hr = HRESULT_FROM_WIN32(GetLastError());
  902. goto EXIT;
  903. }
  904. dwSize = ARRAYSIZE(szComputerName);
  905. if (!GetComputerName(szComputerName, &dwSize))
  906. {
  907. DPF(APPerr, TEXT("Failed to get computer name"));
  908. hr = HRESULT_FROM_WIN32(GetLastError());
  909. goto EXIT;
  910. }
  911. if (!GetSystemWindowsDirectory(szWindir, ARRAYSIZE(szWindir)))
  912. {
  913. DPF(APPerr, TEXT("Failed to get WINDIR"));
  914. hr = HRESULT_FROM_WIN32(GetLastError());
  915. goto EXIT;
  916. }
  917. if (!GetEnvironmentVariable(TEXT("HOMEDRIVE"), szHomeDrive, ARRAYSIZE(szHomeDrive)))
  918. {
  919. DWORD dw = GetLastError();
  920. DPF(APPerr, TEXT("Failed to get HOMEDRIVE"));
  921. hr = HRESULT_FROM_WIN32(GetLastError());
  922. goto EXIT;
  923. }
  924. if (!GetEnvironmentVariable(TEXT("SystemDrive"), szSystemDrive, ARRAYSIZE(szSystemDrive)))
  925. {
  926. DPF(APPerr, TEXT("Failed to get SystemDrive"));
  927. hr = HRESULT_FROM_WIN32(GetLastError());
  928. goto EXIT;
  929. }
  930. hr = StringCchCopy(szBackupDir, ARRAYSIZE(szBackupDir), szWindir);
  931. if (SUCCEEDED(hr))
  932. {
  933. ConcatenatePaths(szBackupDir, CLMT_BACKUP_DIR, ARRAYSIZE(szBackupDir));
  934. if (!CreateDirectory(szBackupDir, NULL))
  935. {
  936. hr = HRESULT_FROM_WIN32(GetLastError());
  937. if (HRESULT_CODE(hr) != ERROR_ALREADY_EXISTS)
  938. {
  939. goto EXIT;
  940. }
  941. }
  942. }
  943. else
  944. {
  945. goto EXIT;
  946. }
  947. hr = GetFirstNTFSDrive(szFirstNTFSDrive, ARRAYSIZE(szFirstNTFSDrive));
  948. if (FAILED(hr))
  949. {
  950. DPF(APPerr, TEXT("Failed to get first NTFS drive in system"));
  951. goto EXIT;
  952. }
  953. //
  954. // Generate strings section depend on operation mode
  955. //
  956. hr = InfGenerateStringsSection(lpInfFile,
  957. szStringSection,
  958. ARRAYSIZE(szStringSection));
  959. if (FAILED(hr))
  960. {
  961. DPF(APPerr, TEXT("InfGenerateStringsSection failed"));
  962. goto EXIT;
  963. }
  964. //
  965. // Update private environment variables to INF file
  966. //
  967. for (i = 0 ; epCLMT[i].lpEnvVarName != NULL ; i++)
  968. {
  969. hr = StringCchPrintf(szStr,
  970. ARRAYSIZE(szStr),
  971. TEXT("\"%s\""),
  972. epCLMT[i].lpValue);
  973. if (SUCCEEDED(hr))
  974. {
  975. BOOL bRet;
  976. bRet = WritePrivateProfileString(szStringSection,
  977. epCLMT[i].lpEnvVarName,
  978. szStr,
  979. lpInfFile);
  980. if (!bRet)
  981. {
  982. hr = HRESULT_FROM_WIN32(GetLastError());
  983. DPF(APPerr, TEXT("Failed to append private variable to INF file"));
  984. break;
  985. }
  986. }
  987. else
  988. {
  989. DPF(APPerr, TEXT("StringCchPrintf failed"));
  990. break;
  991. }
  992. }
  993. EXIT:
  994. DPF(APPmsg, TEXT("Exit UpdateINFFileSys:"));
  995. return hr;
  996. }
  997. //-----------------------------------------------------------------------
  998. //
  999. // Function: InfGenerateStringsSection
  1000. //
  1001. // Descrip: Generate [Strings] section from localized and English
  1002. // sections. If the operation is normal source strings are
  1003. // from localized section and destination strings are from
  1004. // English section. vice versa if the operation is Undo.
  1005. //
  1006. // Returns: HRESULT
  1007. //
  1008. // Notes:
  1009. //
  1010. // History: 03/05/2002 rerkboos Created
  1011. //
  1012. // Notes: none.
  1013. //
  1014. //-----------------------------------------------------------------------
  1015. HRESULT InfGenerateStringsSection(
  1016. LPCTSTR lpInfFile, // INF file name
  1017. LPTSTR lpFinalSection, // Output section name that stores required strings
  1018. SIZE_T cchFinalSection // Size of lpFinalSection in TCHAR
  1019. )
  1020. {
  1021. LPVOID lpBuffer;
  1022. LPVOID lpOldBuffer;
  1023. LPCTSTR lpSection;
  1024. LPCTSTR lpSrcSection;
  1025. LPCTSTR lpDstSection;
  1026. DWORD cbBuffer;
  1027. DWORD cchRead;
  1028. TCHAR szLocSection[16];
  1029. BOOL bRet = TRUE;
  1030. HRESULT hr = S_OK;
  1031. LCID lcidOriginal;
  1032. const TCHAR szFinalSection[] = TEXT("Strings");
  1033. const TCHAR szEngSection[] = TEXT("Strings.0409");
  1034. const TCHAR szPrefixSRC[] = TEXT("SRC_");
  1035. const TCHAR szPrefixDST[] = TEXT("DST_");
  1036. if (lpInfFile == NULL || lpFinalSection == NULL)
  1037. {
  1038. return E_INVALIDARG;
  1039. }
  1040. hr = GetSavedInstallLocale(&lcidOriginal);
  1041. if (SUCCEEDED(hr))
  1042. {
  1043. hr = StringCchPrintf(szLocSection,
  1044. ARRAYSIZE(szLocSection),
  1045. TEXT("Strings.%04X"),
  1046. lcidOriginal);
  1047. }
  1048. if (FAILED(hr))
  1049. {
  1050. return hr;
  1051. }
  1052. if (MyStrCmpI(szLocSection,szEngSection) == LSTR_EQUAL)
  1053. {
  1054. return E_NOTIMPL;
  1055. }
  1056. cbBuffer = 8192;
  1057. lpBuffer = MEMALLOC(cbBuffer);
  1058. if (lpBuffer == NULL)
  1059. {
  1060. return E_OUTOFMEMORY;
  1061. }
  1062. cchRead = GetPrivateProfileSectionNames(lpBuffer,
  1063. cbBuffer / sizeof(TCHAR),
  1064. lpInfFile);
  1065. while (cchRead == (cbBuffer / sizeof(TCHAR)) - 2)
  1066. {
  1067. // Buffer is too small, reallocate until we have enough
  1068. lpOldBuffer = lpBuffer;
  1069. cbBuffer += 8192;
  1070. lpBuffer = MEMREALLOC(lpOldBuffer, cbBuffer);
  1071. if (lpBuffer == NULL)
  1072. {
  1073. MEMFREE(lpOldBuffer);
  1074. return E_OUTOFMEMORY;
  1075. }
  1076. // Read the data from section again
  1077. cchRead = GetPrivateProfileSectionNames(lpBuffer,
  1078. cbBuffer / sizeof(TCHAR),
  1079. lpInfFile);
  1080. }
  1081. // At this point we have big enough buffer and data in it
  1082. if (cchRead > 0)
  1083. {
  1084. lpSection = MultiSzTok(lpBuffer);
  1085. while (lpSection != NULL)
  1086. {
  1087. if (StrStrI(lpSection, TEXT("Strings.")) != NULL)
  1088. {
  1089. // This is one of Strings sections,
  1090. // Delete all sections that do not match current locale and English
  1091. if (MyStrCmpI(lpSection, szLocSection) != LSTR_EQUAL &&
  1092. MyStrCmpI(lpSection, szEngSection) != LSTR_EQUAL)
  1093. {
  1094. bRet = WritePrivateProfileSection(lpSection, NULL, lpInfFile);
  1095. if (!bRet)
  1096. {
  1097. break;
  1098. }
  1099. }
  1100. }
  1101. // Get next section name
  1102. lpSection = MultiSzTok(NULL);
  1103. }
  1104. // no error occured
  1105. bRet = TRUE;
  1106. }
  1107. else
  1108. {
  1109. SetLastError(ERROR_NOT_FOUND);
  1110. bRet = FALSE;
  1111. }
  1112. MEMFREE(lpBuffer);
  1113. if (!bRet)
  1114. {
  1115. return HRESULT_FROM_WIN32(GetLastError());
  1116. }
  1117. //
  1118. // Merge strings from Loc and Eng section to [Strings] section
  1119. //
  1120. if (g_dwRunningStatus != CLMT_UNDO_PROGRAM_FILES
  1121. && g_dwRunningStatus != CLMT_UNDO_APPLICATION_DATA
  1122. && g_dwRunningStatus != CLMT_UNDO_ALL)
  1123. {
  1124. lpSrcSection = szLocSection;
  1125. lpDstSection = szEngSection;
  1126. }
  1127. else
  1128. {
  1129. lpSrcSection = szEngSection;
  1130. lpDstSection = szLocSection;
  1131. }
  1132. // Copy source strings to [Strings] section with SRC_ prefix
  1133. hr = InfCopySectionWithPrefix(lpSrcSection,
  1134. szFinalSection,
  1135. szPrefixSRC,
  1136. lpInfFile);
  1137. if (SUCCEEDED(hr))
  1138. {
  1139. // Copy destination strings to [Strings] section with DSTs_ prefix
  1140. hr = InfCopySectionWithPrefix(lpDstSection,
  1141. szFinalSection,
  1142. szPrefixDST,
  1143. lpInfFile);
  1144. if (SUCCEEDED(hr))
  1145. {
  1146. WritePrivateProfileSection(lpSrcSection, NULL, lpInfFile);
  1147. WritePrivateProfileSection(lpDstSection, NULL, lpInfFile);
  1148. hr = StringCchCopy(lpFinalSection, cchFinalSection, szFinalSection);
  1149. }
  1150. }
  1151. return hr;
  1152. }
  1153. //-----------------------------------------------------------------------
  1154. //
  1155. // Function: InfCopySectionWithPrefix
  1156. //
  1157. // Descrip: Copy keys from source section to destination and append
  1158. // prefix to key name in destination section
  1159. //
  1160. // Returns: HRESULT
  1161. //
  1162. // Notes:
  1163. //
  1164. // History: 03/05/2002 rerkboos Created
  1165. //
  1166. // Notes: none.
  1167. //
  1168. //-----------------------------------------------------------------------
  1169. HRESULT InfCopySectionWithPrefix(
  1170. LPCTSTR lpSrcSection, // Source section name
  1171. LPCTSTR lpDstSection, // Destination section name
  1172. LPCTSTR lpPrefix, // Prefix to add to key name
  1173. LPCTSTR lpInfFile // Inf file name
  1174. )
  1175. {
  1176. HRESULT hr = E_NOTIMPL;
  1177. BOOL bRet;
  1178. LPVOID lpBuffer;
  1179. LPVOID lpOldBuffer;
  1180. DWORD cbBuffer;
  1181. DWORD cchRead;
  1182. LPTSTR lpSz;
  1183. LPTSTR lpKey;
  1184. LPTSTR lpValue;
  1185. TCHAR szPrefixedKey[MAX_PATH];
  1186. if (lpSrcSection == NULL || lpDstSection == NULL || lpInfFile == NULL)
  1187. {
  1188. return E_INVALIDARG;
  1189. }
  1190. //
  1191. // Read data from source section into memory
  1192. //
  1193. cbBuffer = 65536;
  1194. lpBuffer = MEMALLOC(cbBuffer);
  1195. if (lpBuffer == NULL)
  1196. {
  1197. return E_OUTOFMEMORY;
  1198. }
  1199. cchRead = GetPrivateProfileSection(lpSrcSection,
  1200. lpBuffer,
  1201. cbBuffer / sizeof(TCHAR),
  1202. lpInfFile);
  1203. while (cchRead == (cbBuffer / sizeof(TCHAR)) - 2)
  1204. {
  1205. // Buffer is too small, reallocate until we have enough
  1206. lpOldBuffer = lpBuffer;
  1207. cbBuffer += 65536;
  1208. lpBuffer = MEMREALLOC(lpOldBuffer, cbBuffer);
  1209. if (lpBuffer == NULL)
  1210. {
  1211. MEMFREE(lpOldBuffer);
  1212. return E_OUTOFMEMORY;
  1213. }
  1214. // Read the data from section again
  1215. cchRead = GetPrivateProfileSection(lpSrcSection,
  1216. lpBuffer,
  1217. cbBuffer / sizeof(TCHAR),
  1218. lpInfFile);
  1219. }
  1220. //
  1221. // Write key with prefix to destination section
  1222. //
  1223. lpKey = (LPTSTR) MultiSzTok((LPCTSTR) lpBuffer);
  1224. while (lpKey != NULL)
  1225. {
  1226. lpValue = StrStr(lpKey, TEXT("="));
  1227. *lpValue = TEXT('\0');
  1228. hr = StringCchPrintf(szPrefixedKey,
  1229. ARRAYSIZE(szPrefixedKey),
  1230. TEXT("%s%s"),
  1231. lpPrefix,
  1232. lpKey);
  1233. if (FAILED(hr))
  1234. {
  1235. break;
  1236. }
  1237. *lpValue = TEXT('=');
  1238. lpValue++;
  1239. bRet = WritePrivateProfileString(lpDstSection,
  1240. szPrefixedKey,
  1241. lpValue,
  1242. lpInfFile);
  1243. if (!bRet)
  1244. {
  1245. hr = HRESULT_FROM_WIN32(GetLastError());
  1246. break;
  1247. }
  1248. // Get next Sz value
  1249. lpKey = (LPTSTR) MultiSzTok(NULL);
  1250. }
  1251. MEMFREE(lpBuffer);
  1252. return hr;
  1253. }
  1254. //-----------------------------------------------------------------------
  1255. //
  1256. // Function: UpdateINFFilePerUser
  1257. //
  1258. // Descrip: adding user specific key name in [Strings] section
  1259. //
  1260. // Returns: HRESULT
  1261. //
  1262. // Notes:
  1263. //
  1264. // History: 09/17/2001 xiaoz created
  1265. // 03/08/2002 rerkboos modified to work with SRC/DST format
  1266. //
  1267. // Notes:
  1268. //
  1269. //-----------------------------------------------------------------------
  1270. HRESULT UpdateINFFilePerUser(
  1271. LPCTSTR lpInfFile,
  1272. LPCTSTR lpUserName,
  1273. LPCTSTR lpUserSid,
  1274. BOOL bCureMode
  1275. )
  1276. {
  1277. HRESULT hr = S_OK;
  1278. BOOL bRet = FALSE;
  1279. DWORD dwSize;
  1280. TCHAR szExpandedUserProfilePath[MAX_PATH];
  1281. TCHAR szStr[MAX_PATH + 2];
  1282. UINT uInstLocale;
  1283. TCHAR szRegKey[MAX_PATH];
  1284. HRESULT hRes;
  1285. LONG lRet;
  1286. DWORD cbStr;
  1287. const TCHAR szStringsSection[] = TEXT("Strings");
  1288. if (lpInfFile == NULL || lpUserName == NULL)
  1289. {
  1290. hr = E_INVALIDARG;
  1291. goto Cleanup;
  1292. }
  1293. DPF(APPmsg, TEXT("Enter UpdateINFFilePerUser"));
  1294. dwSize = MAX_PATH;
  1295. if (GetDefaultUserProfileDirectory(szExpandedUserProfilePath, &dwSize))
  1296. {
  1297. if (MyStrCmpI(DEFAULT_USER, lpUserName))
  1298. {
  1299. hr = StringCchCopy(szRegKey, ARRAYSIZE(szRegKey), g_cszProfileList);
  1300. if (SUCCEEDED(hr))
  1301. {
  1302. hr = StringCchCat(szRegKey, ARRAYSIZE(szRegKey), TEXT("\\"));
  1303. hr = StringCchCat(szRegKey, ARRAYSIZE(szRegKey), lpUserSid);
  1304. if (SUCCEEDED(hr))
  1305. {
  1306. cbStr = sizeof(szStr);
  1307. lRet = GetRegistryValue(HKEY_LOCAL_MACHINE,
  1308. szRegKey,
  1309. g_cszProfileImagePath,
  1310. (LPBYTE) szStr,
  1311. &cbStr);
  1312. if (lRet == ERROR_SUCCESS)
  1313. {
  1314. ExpandEnvironmentStrings(szStr,
  1315. szExpandedUserProfilePath,
  1316. ARRAYSIZE(szExpandedUserProfilePath));
  1317. }
  1318. else
  1319. {
  1320. hr = E_FAIL;
  1321. }
  1322. }
  1323. }
  1324. if (FAILED(hr))
  1325. {
  1326. DPF(APPerr, TEXT("Failed to get profile directory for user"));
  1327. }
  1328. }
  1329. if (SUCCEEDED(hr))
  1330. {
  1331. hr = StringCchPrintf(szStr,
  1332. ARRAYSIZE(szStr),
  1333. TEXT("\"%s\""),
  1334. szExpandedUserProfilePath);
  1335. }
  1336. }
  1337. else
  1338. {
  1339. hr = HRESULT_FROM_WIN32(GetLastError());
  1340. DPF(APPerr, TEXT("Failed to get default user profile directory"));
  1341. goto Cleanup;
  1342. }
  1343. if (SUCCEEDED(hr))
  1344. {
  1345. if (bCureMode)
  1346. {
  1347. if (!WritePrivateProfileString(szStringsSection,
  1348. lpUserSid,
  1349. szStr,
  1350. lpInfFile))
  1351. {
  1352. hr = HRESULT_FROM_WIN32(GetLastError());
  1353. DPF(APPerr, TEXT("Failed to write environment variable"));
  1354. }
  1355. }
  1356. else
  1357. {
  1358. if (!WritePrivateProfileString(szStringsSection,
  1359. TEXT("USERPROFILE"),
  1360. szStr,
  1361. lpInfFile))
  1362. {
  1363. hr = HRESULT_FROM_WIN32(GetLastError());
  1364. DPF(APPerr, TEXT("Failed to write environment variable"));
  1365. }
  1366. }
  1367. }
  1368. if (!bCureMode)
  1369. {
  1370. if (!WritePrivateProfileString(szStringsSection,
  1371. TEXT("USER_SID"),
  1372. lpUserSid,
  1373. lpInfFile))
  1374. {
  1375. hr = HRESULT_FROM_WIN32(GetLastError());
  1376. DPF(APPerr, TEXT("Failed to write environment variable"));
  1377. goto Cleanup;
  1378. }
  1379. }
  1380. hr = S_OK;
  1381. DPF(APPmsg, TEXT("Exit UpdateINFFilePerUser"));
  1382. Cleanup:
  1383. return hr;
  1384. }
  1385. //-----------------------------------------------------------------------
  1386. //
  1387. // Function: GetInfFilePath
  1388. //
  1389. // Descrip: Get a file name for temp INF file
  1390. //
  1391. // Returns: BOOL
  1392. //
  1393. // Notes:
  1394. //
  1395. // History: 09/17/2001 xiaoz created
  1396. // 03/06/2002 rerkboos Read INF from resource
  1397. //
  1398. // Notes:
  1399. //
  1400. //-----------------------------------------------------------------------
  1401. HRESULT GetInfFilePath(
  1402. LPTSTR lpInfFile, // Output buffer store INF file name
  1403. SIZE_T cchInfFile // Len of buffer in TCHAR
  1404. )
  1405. {
  1406. HRESULT hr = S_OK;
  1407. BOOL bRet = FALSE;
  1408. TCHAR *p;
  1409. TCHAR szSysDir[MAX_PATH];
  1410. TCHAR szInfSource[MAX_PATH];
  1411. TCHAR szTempName[MAX_PATH];
  1412. LPTSTR lpFileName;
  1413. if (!lpInfFile)
  1414. {
  1415. return E_INVALIDARG;
  1416. }
  1417. DPF(dlPrint, TEXT("Enter GetInfFilePath:"));
  1418. // Contruct a tmp file name for our INF in szSysDir
  1419. // The temp INF file is in %windir%\system32\clmt*.tmp
  1420. if (GetSystemDirectory(szSysDir, ARRAYSIZE(szSysDir)))
  1421. {
  1422. if (GetTempFileName(szSysDir, TEXT("clmt"), 0, szTempName))
  1423. {
  1424. hr = S_OK;
  1425. }
  1426. else
  1427. {
  1428. hr = HRESULT_FROM_WIN32(GetLastError());
  1429. DPF(dlError, TEXT("Failed to get temp file name"));
  1430. }
  1431. }
  1432. else
  1433. {
  1434. hr = HRESULT_FROM_WIN32(GetLastError());
  1435. DPF(dlError, TEXT("Failed to get system directory"));
  1436. }
  1437. if (SUCCEEDED(hr))
  1438. {
  1439. // We will use template from inf file if user supply /INF switch
  1440. // otherwise we will grab it from resource section
  1441. if (g_fUseInf)
  1442. {
  1443. //
  1444. // Use user-supply INF as template
  1445. //
  1446. if (GetFullPathName(g_szInfFile,
  1447. ARRAYSIZE(szInfSource),
  1448. szInfSource,
  1449. &lpFileName))
  1450. {
  1451. // Copy the source INF file to %windir%\system32\clmt*.tmp
  1452. if (CopyFile(szInfSource, szTempName, FALSE))
  1453. {
  1454. DPF(dlPrint, TEXT("Use inf from %s"), g_szInfFile);
  1455. hr = StringCchCopy(lpInfFile, cchInfFile, szTempName);
  1456. }
  1457. else
  1458. {
  1459. hr = HRESULT_FROM_WIN32(GetLastError());
  1460. DPF(dlError, TEXT("Failed to copy temporary INF file"));
  1461. }
  1462. }
  1463. else
  1464. {
  1465. hr = HRESULT_FROM_WIN32(GetLastError());
  1466. DPF(dlError, TEXT("%s not found."), g_szInfFile);
  1467. }
  1468. }
  1469. else
  1470. {
  1471. //
  1472. // Use template from resource
  1473. //
  1474. DPF(dlPrint, TEXT("Use INF from resource"));
  1475. hr = GetInfFromResource(szTempName);
  1476. if (SUCCEEDED(hr))
  1477. {
  1478. hr = StringCchCopy(g_szInfFile, ARRAYSIZE(g_szInfFile), szTempName);
  1479. hr = StringCchCopy(lpInfFile, cchInfFile, szTempName);
  1480. }
  1481. else
  1482. {
  1483. DPF(dlError, TEXT("Failed to read INF file from resource"));
  1484. }
  1485. }
  1486. }
  1487. DPF(dlPrint, TEXT("Exit GetInfFilePath:"));
  1488. return hr;
  1489. }
  1490. //-----------------------------------------------------------------------
  1491. //
  1492. // Function: GetInfFromResource
  1493. //
  1494. // Descrip: Read INF file from resource section and write it to output
  1495. // file.
  1496. //
  1497. // Returns: HRESULT
  1498. //
  1499. // Notes:
  1500. //
  1501. // History: 03/08/2002 rerkboos Created
  1502. //
  1503. // Notes:
  1504. //
  1505. //-----------------------------------------------------------------------
  1506. HRESULT GetInfFromResource(
  1507. LPCTSTR lpDstFile // Output file name
  1508. )
  1509. {
  1510. HRESULT hr = E_FAIL;
  1511. HMODULE hExe;
  1512. BOOL bRet = FALSE;
  1513. if (lpDstFile == NULL)
  1514. {
  1515. return E_INVALIDARG;
  1516. }
  1517. // Get the handle to our executable
  1518. hExe = GetModuleHandle(NULL);
  1519. if (hExe)
  1520. {
  1521. // Inf is stored in RCDATA type with the name "CLMTINF"
  1522. HRSRC hRsrc = FindResource(hExe, TEXT("CLMTINF"), RT_RCDATA);
  1523. if (hRsrc)
  1524. {
  1525. DWORD cbBuffer;
  1526. LPVOID lpBuffer;
  1527. cbBuffer = SizeofResource(hExe, hRsrc);
  1528. if (cbBuffer > 0)
  1529. {
  1530. lpBuffer = MEMALLOC(cbBuffer);
  1531. if (lpBuffer)
  1532. {
  1533. HGLOBAL hGlobal = LoadResource(hExe, hRsrc);
  1534. if (hGlobal)
  1535. {
  1536. LPVOID lpLockGlobal = LockResource(hGlobal);
  1537. if (lpLockGlobal)
  1538. {
  1539. HANDLE hFile;
  1540. CopyMemory(lpBuffer, lpLockGlobal, cbBuffer);
  1541. hFile = CreateFile(lpDstFile,
  1542. GENERIC_WRITE,
  1543. FILE_SHARE_READ,
  1544. NULL,
  1545. CREATE_ALWAYS,
  1546. FILE_ATTRIBUTE_TEMPORARY,
  1547. NULL);
  1548. if (hFile != INVALID_HANDLE_VALUE)
  1549. {
  1550. DWORD cbWritten;
  1551. bRet = WriteFile(hFile,
  1552. lpBuffer,
  1553. cbBuffer,
  1554. &cbWritten,
  1555. NULL);
  1556. CloseHandle(hFile);
  1557. }
  1558. }
  1559. }
  1560. MEMFREE(lpBuffer);
  1561. }
  1562. else
  1563. {
  1564. SetLastError(ERROR_OUTOFMEMORY);
  1565. }
  1566. }
  1567. }
  1568. }
  1569. if (!bRet)
  1570. {
  1571. hr = HRESULT_FROM_WIN32(GetLastError());
  1572. }
  1573. else
  1574. {
  1575. hr = S_OK;
  1576. }
  1577. return hr;
  1578. }
  1579. //*************************************************************
  1580. // ReplaceString
  1581. //
  1582. // Purpose: Replace a string
  1583. //
  1584. // Parameter: lpszOldStr: Orignal string
  1585. // lpszReplaceStr: Search string
  1586. // lpszReplacedWithStr: String to be replaced with
  1587. // lpszOutputStr: Output buffer
  1588. // cbszOutputStr: size of output buffer
  1589. // lpszTailCheck: point to predefined tail character
  1590. // lpSysPath: point to standard system path
  1591. // lpAttrib: point to string attribute
  1592. // bStrCheck: True -- do it, or False -- skip it
  1593. //
  1594. // History: 12/10/2001 geoffguo created
  1595. //
  1596. // Note: Tail check is right side check.
  1597. // For example, "Documents" and "Documents and Settings". if you search
  1598. // "Documents", to avoid mismatch, we check the next character of "Documents".
  1599. //*************************************************************
  1600. BOOL ReplaceString(
  1601. LPCTSTR lpszOldStr,
  1602. LPCTSTR lpszReplaceStr,
  1603. LPCTSTR lpszReplacedWithStr,
  1604. LPTSTR lpszOutputStr,
  1605. size_t cbszOutputStr,
  1606. LPCTSTR lpszTailCheck,
  1607. LPCTSTR lpSysPath,
  1608. LPDWORD lpAttrib,
  1609. BOOL bStrCheck)
  1610. {
  1611. BOOL bRet = FALSE;
  1612. DWORD dwLen, dwStrNum;
  1613. LPTSTR pszAnchor = NULL;
  1614. TCHAR cTemp;
  1615. TCHAR *p;
  1616. if (!lpszOldStr || !lpszReplaceStr || !lpszReplacedWithStr || !lpszOutputStr)
  1617. {
  1618. return bRet;
  1619. }
  1620. dwStrNum = 0;
  1621. dwLen = lstrlen(lpszReplaceStr);
  1622. p = (LPTSTR)lpszOldStr;
  1623. lpszOutputStr[0] = TEXT('\0');
  1624. while (*p)
  1625. {
  1626. //get the first occurance of the string needs to be replaced
  1627. pszAnchor = StrStrI(p,lpszReplaceStr);
  1628. if (pszAnchor)
  1629. {
  1630. dwStrNum++;
  1631. if (!bStrCheck || StringValidationCheck(lpszOldStr, lpszReplaceStr, lpSysPath, lpszTailCheck, lpAttrib, dwStrNum))
  1632. {
  1633. cTemp = *pszAnchor;
  1634. *pszAnchor = L'\0';
  1635. if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p)))
  1636. {
  1637. bRet = FALSE;
  1638. goto Exit;
  1639. }
  1640. if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,lpszReplacedWithStr)))
  1641. {
  1642. bRet = FALSE;
  1643. goto Exit;
  1644. }
  1645. *pszAnchor = cTemp;
  1646. bRet = TRUE;
  1647. } else //Copy invalid matching string
  1648. {
  1649. cTemp = *(pszAnchor+dwLen);
  1650. *(pszAnchor+dwLen) = L'\0';
  1651. if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p)))
  1652. {
  1653. bRet = FALSE;
  1654. goto Exit;
  1655. }
  1656. *(pszAnchor+dwLen) = cTemp;
  1657. }
  1658. p = pszAnchor+dwLen;
  1659. }
  1660. else //Copy string
  1661. {
  1662. if (FAILED(StringCchCat(lpszOutputStr,cbszOutputStr,p)))
  1663. {
  1664. bRet = FALSE;
  1665. goto Exit;
  1666. }
  1667. break;
  1668. }
  1669. }
  1670. Exit:
  1671. return bRet;
  1672. }
  1673. //-----------------------------------------------------------------------
  1674. //
  1675. // Function: StringMultipleReplacement
  1676. //
  1677. // Descrip: string replacement with multiple replace pair
  1678. //
  1679. // Returns: HRESULT
  1680. //
  1681. // Notes:
  1682. //
  1683. // History: 09/17/2001 xiaoz created
  1684. //
  1685. // Notes:
  1686. // lpszOldStr : The source string
  1687. // lpszReplaceMSzStr : multi string instance that needs to be replaced
  1688. // lpszReplacedWithMSzStr : multi string instance that will replace to
  1689. // lpszOutputStr: output buffer
  1690. // cbszOutputStr:buffer size for lpszOutputStr
  1691. //
  1692. //-----------------------------------------------------------------------
  1693. HRESULT StringMultipleReplacement(
  1694. LPCTSTR lpszOldStr,
  1695. LPCTSTR lpszReplaceMSzStr,
  1696. LPCTSTR lpszReplacedWithMSzStr,
  1697. LPTSTR lpszOutputStr,
  1698. size_t cchOutputStr)
  1699. {
  1700. HRESULT hr;
  1701. DWORD dwLen;
  1702. LPTSTR pszAnchor = NULL;
  1703. TCHAR cTemp;
  1704. LPTSTR pOld,pNew;
  1705. LPTSTR pTmp = NULL;
  1706. TCHAR cNonChar = TEXT('\xFFFF');
  1707. if (!lpszOldStr || !lpszReplaceMSzStr || !lpszReplacedWithMSzStr || !lpszOutputStr)
  1708. {
  1709. hr = E_INVALIDARG;
  1710. goto Cleanup;
  1711. }
  1712. pOld = (LPTSTR)lpszReplaceMSzStr;
  1713. pNew = (LPTSTR)lpszReplacedWithMSzStr;
  1714. //alloc temp buffer for intermediate string
  1715. pTmp = malloc(cchOutputStr*sizeof(TCHAR));
  1716. if (!pTmp)
  1717. {
  1718. hr = E_OUTOFMEMORY;
  1719. goto Cleanup;
  1720. }
  1721. if (FAILED(hr = StringCchCopy(pTmp,cchOutputStr,lpszOldStr)))
  1722. {
  1723. goto Cleanup;
  1724. }
  1725. while (*pOld && *pNew)
  1726. {
  1727. if (!ReplaceString(pTmp,pOld,pNew,lpszOutputStr, cchOutputStr,&cNonChar, NULL, NULL, TRUE))
  1728. {
  1729. hr = E_OUTOFMEMORY;
  1730. goto Cleanup;
  1731. }
  1732. pOld += (lstrlen(pOld) + 1);
  1733. pNew += (lstrlen(pNew) + 1);
  1734. if (FAILED(hr = StringCchCopy(pTmp,cchOutputStr,lpszOutputStr)))
  1735. {
  1736. goto Cleanup;
  1737. }
  1738. }
  1739. hr = S_OK;
  1740. Cleanup:
  1741. FreePointer(pTmp);
  1742. return hr;
  1743. }
  1744. //-----------------------------------------------------------------------
  1745. //
  1746. // Function: MultiSzSubStr
  1747. //
  1748. // Descrip: multiSZ version of substr
  1749. //
  1750. // Returns: BOOL
  1751. //
  1752. // Notes:
  1753. //
  1754. // History: 09/17/2001 xiaoz created
  1755. //
  1756. // Notes: return TRUE is szString is a sub string of a string in szMultiSz
  1757. //
  1758. //-----------------------------------------------------------------------
  1759. BOOL
  1760. MultiSzSubStr (
  1761. LPTSTR szString,
  1762. LPTSTR szMultiSz)
  1763. {
  1764. TCHAR *p = szMultiSz;
  1765. while (*p)
  1766. {
  1767. if (StrStrI(p,szString))
  1768. {
  1769. return TRUE;
  1770. }
  1771. p += (lstrlen(p) + 1);
  1772. }
  1773. return FALSE;
  1774. }
  1775. //-----------------------------------------------------------------------
  1776. //
  1777. // Function: IsStrInMultiSz
  1778. //
  1779. // Descrip: check whether is string is in MultiSz
  1780. //
  1781. // Returns: BOOL
  1782. //
  1783. // Notes:
  1784. //
  1785. // History: 09/17/2001 xiaoz created
  1786. //
  1787. // Notes:
  1788. //
  1789. //-----------------------------------------------------------------------
  1790. BOOL
  1791. IsStrInMultiSz (
  1792. LPCTSTR szString,
  1793. LPCTSTR szMultiSz)
  1794. {
  1795. LPCTSTR p = szMultiSz;
  1796. while (*p)
  1797. {
  1798. if (!MyStrCmpI(p,szString))
  1799. {
  1800. return TRUE;
  1801. }
  1802. p += (lstrlen(p) + 1);
  1803. }
  1804. return FALSE;
  1805. }
  1806. //-----------------------------------------------------------------------
  1807. //
  1808. // Function: MultiSzLen
  1809. //
  1810. // Descrip: Returns the length (in characters) of the buffer required to hold a multisz,
  1811. // INCLUDING the trailing null.
  1812. //
  1813. // Returns: DWORD
  1814. //
  1815. // Notes:
  1816. //
  1817. // History: 09/17/2001 xiaoz created
  1818. //
  1819. // Notes:
  1820. // Example: MultiSzLen("foo\0bar\0") returns 9
  1821. //
  1822. //-----------------------------------------------------------------------
  1823. DWORD MultiSzLen(LPCTSTR szMultiSz)
  1824. {
  1825. TCHAR *p = (LPTSTR) szMultiSz;
  1826. DWORD dwLen = 0;
  1827. if (!p)
  1828. {
  1829. return 0;
  1830. }
  1831. if (!*p)
  1832. {
  1833. return 2;
  1834. }
  1835. while (*p)
  1836. {
  1837. dwLen += (lstrlen(p) +1);
  1838. p += (lstrlen(p) + 1);
  1839. }
  1840. // add one for the trailing null character
  1841. return (dwLen+1);
  1842. }
  1843. //-----------------------------------------------------------------------
  1844. //
  1845. // Function: MultiSzTok
  1846. //
  1847. // Descrip: Extract an sz string from multisz string
  1848. // (work similar to strtok, but use '\0' as seperator)
  1849. //
  1850. // Returns: Pointer to next Sz string
  1851. // NULL if no string left
  1852. //
  1853. // Notes:
  1854. //
  1855. // History: 03/05/2002 rerkboos Created
  1856. //
  1857. // Notes: Supply the pointer to multisz string the first time calling
  1858. // this function. Supply NULL for subsequent call to get
  1859. // next sz string in multisz.
  1860. //
  1861. //-----------------------------------------------------------------------
  1862. LPCTSTR MultiSzTok(
  1863. LPCTSTR lpMultiSz // Pointer to multisz string
  1864. )
  1865. {
  1866. LPCTSTR lpCurrentSz;
  1867. static LPCTSTR lpNextSz;
  1868. if (lpMultiSz != NULL)
  1869. {
  1870. lpNextSz = lpMultiSz;
  1871. }
  1872. lpCurrentSz = lpNextSz;
  1873. // Advance pointer to next Sz
  1874. while (*lpNextSz != TEXT('\0'))
  1875. {
  1876. lpNextSz++;
  1877. }
  1878. lpNextSz++;
  1879. return (*lpCurrentSz == TEXT('\0') ? NULL : lpCurrentSz);
  1880. }
  1881. //-----------------------------------------------------------------------
  1882. //
  1883. // Function: CmpMultiSzi
  1884. //
  1885. // Descrip: check whether 2 multisz is equal(case insensitive)
  1886. //
  1887. // Returns: BOOL
  1888. //
  1889. // Notes:
  1890. //
  1891. // History: 09/17/2001 xiaoz created
  1892. //
  1893. // Notes: here if stra ="foo1\0foo2\0" and strb = "foo2\0foo1\0"
  1894. // it will return equal , in other words, the string order
  1895. // in multi-sz is not playing role in comparing
  1896. //
  1897. //-----------------------------------------------------------------------
  1898. BOOL CmpMultiSzi(
  1899. LPCTSTR szMultiSz1,
  1900. LPCTSTR szMultiSz2)
  1901. {
  1902. LPCTSTR p;
  1903. if (MultiSzLen(szMultiSz1) != MultiSzLen(szMultiSz2))
  1904. {
  1905. return FALSE;
  1906. }
  1907. p = szMultiSz1;
  1908. while (*p)
  1909. {
  1910. if (!IsStrInMultiSz(p,szMultiSz2))
  1911. {
  1912. return FALSE;
  1913. }
  1914. p += (lstrlen(p) + 1);
  1915. }
  1916. return TRUE;
  1917. }
  1918. //-----------------------------------------------------------------------
  1919. //
  1920. // Function: AppendSzToMultiSz
  1921. //
  1922. // Descrip: appending a string to multiSZ
  1923. //
  1924. // Returns: BOOL
  1925. //
  1926. // Notes:
  1927. //
  1928. // History: 09/17/2001 xiaoz created
  1929. //
  1930. // Notes: return true if succeed, since it will do malloc and the current multiSZ
  1931. // string buffer is too small to append a string, so the API will possible
  1932. // return false, call GetLastError to get error code
  1933. //
  1934. //-----------------------------------------------------------------------
  1935. BOOL
  1936. AppendSzToMultiSz(
  1937. IN LPCTSTR SzToAppend,
  1938. IN OUT LPTSTR *MultiSz,
  1939. IN OUT PDWORD pcchMultiSzLen //MultiSz buffer size in char
  1940. )
  1941. {
  1942. DWORD cchszLen;
  1943. DWORD cchmultiSzLen;
  1944. LPTSTR newMultiSz = NULL;
  1945. LPTSTR lpStartPoint = NULL;
  1946. LPTSTR lpSpTChar = NULL;
  1947. BOOL bMemEnlarged = FALSE;
  1948. DWORD cchLen;
  1949. BOOL bRet = FALSE;
  1950. HRESULT hr;
  1951. //SzToAppend can not be null or empty
  1952. if (!SzToAppend || !SzToAppend[0])
  1953. {
  1954. SetLastError(ERROR_INVALID_PARAMETER);
  1955. goto Exit;
  1956. }
  1957. //Multi-SZ must be initialzed , not NULL pointer, at least 2 '\0'
  1958. if (!MultiSz || *pcchMultiSzLen < 2)
  1959. {
  1960. SetLastError(ERROR_INVALID_PARAMETER);
  1961. goto Exit;
  1962. }
  1963. // get the size, of the two buffers in TCHAR
  1964. cchszLen = lstrlen(SzToAppend)+1;
  1965. cchmultiSzLen = MultiSzLen(*MultiSz);
  1966. if (cchszLen + cchmultiSzLen > *pcchMultiSzLen)
  1967. {
  1968. newMultiSz = (LPTSTR)malloc( (cchszLen+cchmultiSzLen+MULTI_SZ_BUF_DELTA) * sizeof(TCHAR) );
  1969. if( newMultiSz == NULL )
  1970. {
  1971. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1972. goto Exit;
  1973. }
  1974. // recopy the old MultiSz into proper position into the new buffer.
  1975. // the (char*) cast is necessary, because newMultiSz may be a wchar*, and
  1976. // szLen is in bytes.
  1977. memcpy( ((char*)newMultiSz), *MultiSz, cchmultiSzLen * sizeof(TCHAR));
  1978. bMemEnlarged = TRUE;
  1979. cchLen = cchszLen + cchmultiSzLen + MULTI_SZ_BUF_DELTA;
  1980. }
  1981. else
  1982. {
  1983. newMultiSz = *MultiSz;
  1984. cchLen = *pcchMultiSzLen;
  1985. }
  1986. //the existing sz ended with 2 NULL, we need to start to copy the string
  1987. // from second null char
  1988. //lpStartPoint = (char*)newMultiSz + (multiSzLen - 1) * sizeof(TCHAR);
  1989. if (cchmultiSzLen == 2)
  1990. {
  1991. //if it's empty MultiSz, we do not need to keep the 1st NULL
  1992. cchmultiSzLen = 0;
  1993. lpStartPoint = newMultiSz;
  1994. }
  1995. else
  1996. {
  1997. lpStartPoint = newMultiSz + (cchmultiSzLen - 1);
  1998. }
  1999. // copy in the new string
  2000. lpSpTChar = (TCHAR*) lpStartPoint;
  2001. if (FAILED(hr = StringCchCopy(lpSpTChar,cchLen - (cchmultiSzLen - 1) , SzToAppend )))
  2002. {
  2003. SetLastError(HRESULT_CODE(hr));
  2004. goto Exit;
  2005. }
  2006. //Add the ending NULL
  2007. *(lpSpTChar+lstrlen(SzToAppend)+1) = 0;
  2008. if (bMemEnlarged)
  2009. {
  2010. free( *MultiSz );
  2011. *MultiSz = newMultiSz;
  2012. *pcchMultiSzLen = cchszLen + cchmultiSzLen + MULTI_SZ_BUF_DELTA;
  2013. }
  2014. SetLastError(ERROR_SUCCESS);
  2015. bRet = TRUE;
  2016. Exit:
  2017. if (!bRet)
  2018. {
  2019. if (newMultiSz)
  2020. {
  2021. free(newMultiSz);
  2022. }
  2023. }
  2024. return bRet;
  2025. }
  2026. //-----------------------------------------------------------------------
  2027. //
  2028. // Function: PrintMultiSz
  2029. //
  2030. // Descrip:
  2031. //
  2032. // Returns: BOOL
  2033. //
  2034. // Notes:
  2035. //
  2036. // History: 09/17/2001 xiaoz created
  2037. //
  2038. // Notes: internal used for debug perpose
  2039. //
  2040. //-----------------------------------------------------------------------
  2041. void PrintMultiSz(LPTSTR MultiSz)
  2042. {
  2043. TCHAR *p = MultiSz;
  2044. while (*p)
  2045. {
  2046. _tprintf(TEXT(" %s"),p);
  2047. _tprintf(TEXT("\n"));
  2048. p += (lstrlen(p) + 1);
  2049. }
  2050. }
  2051. //-----------------------------------------------------------------------
  2052. //
  2053. // Function: GetSetUserProfilePath
  2054. //
  2055. // Descrip: Get or Set User Profile path from registry
  2056. //
  2057. // Returns: BOOL
  2058. //
  2059. // Notes:
  2060. //
  2061. // History: 09/17/2001 xiaoz created
  2062. //
  2063. // Notes:
  2064. // szUserName: User name
  2065. // szPath : Profile path for set and buffer to get profile path for read
  2066. // nOperation: PROFILE_PATH_READ for get path and PROFILE_PATH_WRITE for
  2067. // set path
  2068. // nType : Specifes string type, only used to read though
  2069. // REG_SZ : for unicode string
  2070. // REG_EXPAND_SZ : for unicode string conatins enviroment variable
  2071. //
  2072. //-----------------------------------------------------------------------
  2073. HRESULT GetSetUserProfilePath(
  2074. LPCTSTR szUserName,
  2075. LPTSTR szPath,
  2076. size_t cchPath,
  2077. UINT nOperation,
  2078. UINT nType)
  2079. {
  2080. PSID pSID =NULL;
  2081. DWORD cbSID = 1024;
  2082. TCHAR lpszDomain[MAXDOMAINLENGTH];
  2083. DWORD cchDomainName = MAXDOMAINLENGTH;
  2084. SID_NAME_USE snuType;
  2085. LPTSTR szStrSid = NULL;
  2086. LPTSTR lpszRegRegProfilePath = NULL;
  2087. HKEY hKeyProfileList = NULL;
  2088. DWORD dwErr, dwType, cbUserProfilePath;
  2089. DWORD dwSize;
  2090. size_t cchLen;
  2091. TCHAR szUserProfilePath[MAX_PATH],szExpandedUserProfilePath[MAX_PATH];
  2092. LPTSTR lpszUserProfilePath = szUserProfilePath;
  2093. LPTSTR lpszExpandedUserProfilePath = szExpandedUserProfilePath;
  2094. HRESULT hr;
  2095. pSID = (PSID) LocalAlloc(LPTR, cbSID);
  2096. if (!pSID)
  2097. {
  2098. hr = E_OUTOFMEMORY;
  2099. goto Cleanup;
  2100. }
  2101. if (!LookupAccountName(NULL,szUserName,pSID,&cbSID,lpszDomain,
  2102. &cchDomainName,&snuType))
  2103. {
  2104. hr = HRESULT_FROM_WIN32(GetLastError());
  2105. goto Cleanup;
  2106. }
  2107. if (!IsValidSid(pSID))
  2108. {
  2109. hr = E_FAIL;
  2110. goto Cleanup;
  2111. }
  2112. if (!ConvertSidToStringSid(pSID,&szStrSid))
  2113. {
  2114. hr = E_FAIL;
  2115. goto Cleanup;
  2116. }
  2117. cchLen = lstrlen(g_cszProfileList)+ lstrlen(szStrSid) + 3;
  2118. if (!(lpszRegRegProfilePath = malloc(cchLen * sizeof(TCHAR))))
  2119. {
  2120. hr = E_OUTOFMEMORY;
  2121. goto Cleanup;
  2122. }
  2123. if (FAILED(hr = StringCchPrintf(lpszRegRegProfilePath,cchLen,_T("%s\\%s"),g_cszProfileList,szStrSid)))
  2124. {
  2125. goto Cleanup;
  2126. }
  2127. if ( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  2128. lpszRegRegProfilePath,
  2129. 0,
  2130. KEY_ALL_ACCESS,
  2131. &hKeyProfileList )) != ERROR_SUCCESS )
  2132. {
  2133. hr = HRESULT_FROM_WIN32(dwErr);
  2134. goto Cleanup;
  2135. }
  2136. if (nOperation == PROFILE_PATH_READ)
  2137. {
  2138. cbUserProfilePath = MAX_PATH;
  2139. dwErr = RegQueryValueEx( hKeyProfileList,
  2140. g_cszProfileImagePath,
  2141. NULL,
  2142. &dwType,
  2143. (PBYTE)lpszUserProfilePath,
  2144. &cbUserProfilePath );
  2145. if (dwErr == ERROR_MORE_DATA)
  2146. {
  2147. lpszUserProfilePath = malloc(cbUserProfilePath * sizeof(TCHAR));
  2148. if (!lpszUserProfilePath)
  2149. {
  2150. hr = E_OUTOFMEMORY;
  2151. goto Cleanup;
  2152. }
  2153. dwErr = RegQueryValueEx(hKeyProfileList,
  2154. g_cszProfileImagePath,
  2155. NULL,
  2156. &dwType,
  2157. (PBYTE)lpszUserProfilePath,
  2158. &cbUserProfilePath );
  2159. }
  2160. }
  2161. else
  2162. { // for witre operation
  2163. dwErr = RegSetValueEx(hKeyProfileList,
  2164. g_cszProfileImagePath,
  2165. 0,
  2166. REG_EXPAND_SZ,
  2167. (const BYTE *)szPath,
  2168. (lstrlen(szPath)+1)*sizeof(TCHAR));
  2169. }
  2170. if ( dwErr != ERROR_SUCCESS )
  2171. {
  2172. hr = HRESULT_FROM_WIN32(GetLastError());
  2173. goto Cleanup;
  2174. }
  2175. //The string saved in registry contains enviroment variable, so
  2176. //if user want expanded version, we will do it here
  2177. if (nOperation == PROFILE_PATH_READ)
  2178. {
  2179. if (nType == REG_SZ)
  2180. {
  2181. size_t cchLenForExpandedStr;
  2182. cchLenForExpandedStr = ExpandEnvironmentStrings(
  2183. lpszUserProfilePath,
  2184. lpszExpandedUserProfilePath,
  2185. MAX_PATH);
  2186. if (!cchLenForExpandedStr)
  2187. {
  2188. hr = HRESULT_FROM_WIN32(GetLastError());
  2189. goto Cleanup;
  2190. }
  2191. else if (cchLenForExpandedStr >= MAX_PATH)
  2192. {
  2193. lpszExpandedUserProfilePath = malloc(cchLenForExpandedStr * sizeof(TCHAR));
  2194. if (!lpszExpandedUserProfilePath)
  2195. {
  2196. hr = E_OUTOFMEMORY;
  2197. goto Cleanup;
  2198. }
  2199. if (!ExpandEnvironmentStrings(lpszUserProfilePath,
  2200. lpszExpandedUserProfilePath,
  2201. cchLenForExpandedStr))
  2202. {
  2203. hr = HRESULT_FROM_WIN32(GetLastError());
  2204. goto Cleanup;
  2205. }
  2206. }
  2207. if (FAILED(hr = StringCchCopy(szPath,cchPath,lpszExpandedUserProfilePath)))
  2208. {
  2209. goto Cleanup;
  2210. }
  2211. }
  2212. else
  2213. {
  2214. if (FAILED(StringCchCopy(szPath,cchPath,lpszUserProfilePath)))
  2215. {
  2216. goto Cleanup;
  2217. }
  2218. }
  2219. }
  2220. hr = S_OK;
  2221. Cleanup:
  2222. if (hKeyProfileList)
  2223. {
  2224. RegCloseKey( hKeyProfileList );
  2225. }
  2226. if (pSID)
  2227. {
  2228. FreeSid(pSID);
  2229. }
  2230. if (szStrSid)
  2231. {
  2232. LocalFree(szStrSid);
  2233. }
  2234. FreePointer(lpszRegRegProfilePath);
  2235. if (!lpszUserProfilePath && (lpszUserProfilePath != szUserProfilePath))
  2236. {
  2237. free(lpszUserProfilePath);
  2238. }
  2239. if (!lpszExpandedUserProfilePath && (lpszExpandedUserProfilePath != szUserProfilePath))
  2240. {
  2241. free(lpszExpandedUserProfilePath);
  2242. }
  2243. return (hr);
  2244. }
  2245. //-----------------------------------------------------------------------
  2246. //
  2247. // Function: ReStartSystem
  2248. //
  2249. // Descrip: logoff or reboot the system
  2250. //
  2251. // Returns: none
  2252. //
  2253. // Notes:
  2254. //
  2255. // History: 09/17/2001 xiaoz created
  2256. //
  2257. // Notes:
  2258. //
  2259. //-----------------------------------------------------------------------
  2260. void ReStartSystem(UINT uFlags)
  2261. {
  2262. HANDLE Token = NULL;
  2263. ULONG ReturnLength, Index;
  2264. PTOKEN_PRIVILEGES NewState = NULL;
  2265. PTOKEN_PRIVILEGES OldState = NULL;
  2266. BOOL Result;
  2267. Result = OpenProcessToken( GetCurrentProcess(),
  2268. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  2269. &Token );
  2270. if (Result)
  2271. {
  2272. ReturnLength = 4096;
  2273. NewState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  2274. OldState = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, ReturnLength);
  2275. Result = (BOOL)((NewState != NULL) && (OldState != NULL));
  2276. if (Result)
  2277. {
  2278. Result = GetTokenInformation( Token, // TokenHandle
  2279. TokenPrivileges, // TokenInformationClass
  2280. NewState, // TokenInformation
  2281. ReturnLength, // TokenInformationLength
  2282. &ReturnLength ); // ReturnLength
  2283. if (Result)
  2284. {
  2285. //
  2286. // Set the state settings so that all privileges are enabled...
  2287. //
  2288. if (NewState->PrivilegeCount > 0)
  2289. {
  2290. for (Index = 0; Index < NewState->PrivilegeCount; Index++)
  2291. {
  2292. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  2293. }
  2294. }
  2295. Result = AdjustTokenPrivileges( Token, // TokenHandle
  2296. FALSE, // DisableAllPrivileges
  2297. NewState, // NewState
  2298. ReturnLength, // BufferLength
  2299. OldState, // PreviousState
  2300. &ReturnLength ); // ReturnLength
  2301. if (Result)
  2302. {
  2303. //ExitWindowsEx(uFlags, 0);
  2304. InitiateSystemShutdownEx(NULL,NULL,0,TRUE,TRUE,
  2305. SHTDN_REASON_MAJOR_OPERATINGSYSTEM|SHTDN_REASON_MINOR_UPGRADE);
  2306. AdjustTokenPrivileges( Token,
  2307. FALSE,
  2308. OldState,
  2309. 0,
  2310. NULL,
  2311. NULL );
  2312. }
  2313. }
  2314. }
  2315. }
  2316. if (NewState != NULL)
  2317. {
  2318. LocalFree(NewState);
  2319. }
  2320. if (OldState != NULL)
  2321. {
  2322. LocalFree(OldState);
  2323. }
  2324. if (Token != NULL)
  2325. {
  2326. CloseHandle(Token);
  2327. }
  2328. }
  2329. //-----------------------------------------------------------------------
  2330. //
  2331. // Function: DoMessageBox
  2332. //
  2333. // Descrip: Wrapper for MessageBox
  2334. //
  2335. // Returns: UINT
  2336. //
  2337. // Notes:
  2338. //
  2339. // History: 09/17/2001 xiaoz created
  2340. //
  2341. // Notes:
  2342. //
  2343. //-----------------------------------------------------------------------
  2344. int DoMessageBox(HWND hwndParent, UINT uIdString, UINT uIdCaption, UINT uType)
  2345. {
  2346. TCHAR szString[MAX_PATH+MAX_PATH];
  2347. TCHAR szCaption[MAX_PATH];
  2348. szString[0] = szCaption[0] = TEXT('\0');
  2349. if (uIdString)
  2350. LoadString(g_hInstDll, uIdString, szString, MAX_PATH+MAX_PATH-1);
  2351. if (uIdCaption)
  2352. LoadString(g_hInstDll, uIdCaption, szCaption, MAX_PATH-1);
  2353. return MessageBox(hwndParent, szString, szCaption, uType);
  2354. }
  2355. //-----------------------------------------------------------------------
  2356. //
  2357. // Function: DoMessageBox
  2358. //
  2359. // Descrip: Wrapper for MessageBox
  2360. //
  2361. // Returns: UINT
  2362. //
  2363. // Notes:
  2364. //
  2365. // History: 09/17/2001 xiaoz created
  2366. //
  2367. // Notes:
  2368. //
  2369. //-----------------------------------------------------------------------
  2370. BOOL
  2371. Str2KeyPath(
  2372. IN LPTSTR String,
  2373. OUT PHKEY Data,
  2374. OUT LPTSTR *pSubKeyPath
  2375. )
  2376. {
  2377. UINT i;
  2378. TCHAR *p,ch;
  2379. DWORD cchStrlen;
  2380. STRING_TO_DATA InfRegSpecTohKey[] = {
  2381. TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE,
  2382. TEXT("HKLM") , HKEY_LOCAL_MACHINE,
  2383. TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT,
  2384. TEXT("HKCR") , HKEY_CLASSES_ROOT,
  2385. TEXT("HKR") , NULL,
  2386. TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER,
  2387. TEXT("HKCU") , HKEY_CURRENT_USER,
  2388. TEXT("HKEY_USERS") , HKEY_USERS,
  2389. TEXT("HKU") , HKEY_USERS,
  2390. TEXT("") , NULL
  2391. };
  2392. PSTRING_TO_DATA Table = InfRegSpecTohKey;
  2393. if ( !String || !String[0])
  2394. {
  2395. *pSubKeyPath = NULL;
  2396. *Data = NULL;
  2397. return TRUE;
  2398. }
  2399. for(i=0; Table[i].String[0]; i++)
  2400. {
  2401. cchStrlen = _tcslen(Table[i].String);
  2402. if (_tcslen(String) < cchStrlen)
  2403. {
  2404. continue;
  2405. }
  2406. ch = String[cchStrlen];
  2407. String[cchStrlen] = 0;
  2408. if(!MyStrCmpI(Table[i].String,String))
  2409. {
  2410. *Data = Table[i].Data;
  2411. String[cchStrlen] = ch;
  2412. *pSubKeyPath = &(String[cchStrlen+1]);
  2413. return(TRUE);
  2414. }
  2415. String[cchStrlen] = ch;
  2416. }
  2417. //if we can not find the prefix defined
  2418. //we think it's for user registery
  2419. //In this case ,we return PHKEY as NULL, and pSubKeyPath = String
  2420. *pSubKeyPath = String;
  2421. *Data = NULL;
  2422. return TRUE;
  2423. }
  2424. BOOL
  2425. HKey2Str(
  2426. IN HKEY hKey,
  2427. IN LPTSTR pKeyPath,
  2428. IN size_t cbKeyPath
  2429. )
  2430. {
  2431. UINT i;
  2432. TCHAR *p,ch;
  2433. size_t nStrlen;
  2434. STRING_TO_DATA InfRegSpecTohKey[] = {
  2435. TEXT("HKLM") , HKEY_LOCAL_MACHINE,
  2436. TEXT("HKCR") , HKEY_CLASSES_ROOT,
  2437. TEXT("HKCU") , HKEY_CURRENT_USER,
  2438. TEXT("HKU") , HKEY_USERS,
  2439. TEXT("") , NULL
  2440. };
  2441. PSTRING_TO_DATA Table = InfRegSpecTohKey;
  2442. for(i=0; Table[i].Data; i++)
  2443. {
  2444. if (hKey == Table[i].Data)
  2445. {
  2446. if (SUCCEEDED(StringCchCopy(pKeyPath,cbKeyPath,Table[i].String)))
  2447. {
  2448. return TRUE;
  2449. }
  2450. else
  2451. {
  2452. return FALSE;
  2453. }
  2454. }
  2455. }
  2456. return(FALSE);
  2457. }
  2458. //-----------------------------------------------------------------------------
  2459. //
  2460. // Function: Str2KeyPath2
  2461. //
  2462. // Synopsis: Return the HKEY_xxx value associcated with string value
  2463. //
  2464. // Returns: REG_xxx value
  2465. //
  2466. // History: 02/07/2002 Rerkboos Created
  2467. //
  2468. // Notes: none
  2469. //
  2470. //-----------------------------------------------------------------------------
  2471. BOOL Str2KeyPath2(
  2472. LPCTSTR lpHKeyStr,
  2473. PHKEY pHKey,
  2474. LPCTSTR* pSubKeyPath
  2475. )
  2476. {
  2477. int i;
  2478. LPCTSTR lpStart;
  2479. STRING_TO_DATA InfRegSpecTohKey[] = {
  2480. TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE,
  2481. TEXT("HKLM") , HKEY_LOCAL_MACHINE,
  2482. TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT,
  2483. TEXT("HKCR") , HKEY_CLASSES_ROOT,
  2484. TEXT("HKR") , NULL,
  2485. TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER,
  2486. TEXT("HKCU") , HKEY_CURRENT_USER,
  2487. TEXT("HKEY_USERS") , HKEY_USERS,
  2488. TEXT("HKU") , HKEY_USERS,
  2489. TEXT("") , NULL
  2490. };
  2491. PSTRING_TO_DATA Table = InfRegSpecTohKey;
  2492. if (NULL == lpHKeyStr)
  2493. {
  2494. return FALSE;
  2495. }
  2496. for(i = 0 ; Table[i].String[0] != TEXT('\0') ; i++)
  2497. {
  2498. lpStart = _tcsstr(lpHKeyStr, Table[i].String);
  2499. if (lpStart == lpHKeyStr)
  2500. {
  2501. //
  2502. // Assign the values back to caller, if caller supply the pointers
  2503. //
  2504. if (NULL != pHKey)
  2505. {
  2506. *pHKey = Table[i].Data;
  2507. }
  2508. if (NULL != pSubKeyPath)
  2509. {
  2510. lpStart += lstrlen(Table[i].String);
  2511. if (*lpStart == TEXT('\0'))
  2512. {
  2513. *pSubKeyPath = lpStart;
  2514. }
  2515. else
  2516. {
  2517. *pSubKeyPath = lpStart + 1;
  2518. }
  2519. }
  2520. return TRUE;
  2521. }
  2522. }
  2523. return FALSE;
  2524. }
  2525. //-----------------------------------------------------------------------------
  2526. //
  2527. // Function: Str2REG
  2528. //
  2529. // Synopsis: Convert the registry type string to REG_xxx value
  2530. //
  2531. // Returns: REG_xxx value
  2532. //
  2533. // History: 02/07/2002 Rerkboos Created
  2534. //
  2535. // Notes: none
  2536. //
  2537. //-----------------------------------------------------------------------------
  2538. DWORD Str2REG(
  2539. LPCTSTR lpStrType // String of registry type
  2540. )
  2541. {
  2542. INT nIndex;
  2543. struct _STRING_TO_REG
  2544. {
  2545. TCHAR szStrType[32];
  2546. DWORD dwType;
  2547. };
  2548. // Mapping table from string to REG_xxx value
  2549. struct _STRING_TO_REG arrRegEntries[] = {
  2550. TEXT("REG_BINARY"), REG_BINARY,
  2551. TEXT("REG_DWORD"), REG_DWORD,
  2552. TEXT("REG_DWORD_LITTLE_ENDIAN"), REG_DWORD_LITTLE_ENDIAN,
  2553. TEXT("REG_DWORD_BIG_ENDIAN"), REG_DWORD_BIG_ENDIAN,
  2554. TEXT("REG_EXPAND_SZ"), REG_EXPAND_SZ,
  2555. TEXT("REG_LINK"), REG_LINK,
  2556. TEXT("REG_MULTI_SZ"), REG_MULTI_SZ,
  2557. TEXT("REG_NONE"), REG_NONE,
  2558. TEXT("REG_QWORD"), REG_QWORD,
  2559. TEXT("REG_QWORD_LITTLE_ENDIAN"), REG_QWORD_LITTLE_ENDIAN,
  2560. TEXT("REG_RESOUCE_LIST"), REG_RESOURCE_LIST,
  2561. TEXT("REG_SZ"), REG_SZ,
  2562. TEXT(""), 0
  2563. };
  2564. if (lpStrType == NULL)
  2565. {
  2566. return REG_NONE;
  2567. }
  2568. for (nIndex = 0 ; arrRegEntries[nIndex].szStrType[0] != TEXT('\0') ; nIndex++)
  2569. {
  2570. if (MyStrCmpI(lpStrType, arrRegEntries[nIndex].szStrType) == 0)
  2571. {
  2572. return arrRegEntries[nIndex].dwType;
  2573. }
  2574. }
  2575. return REG_NONE;
  2576. }
  2577. //*************************************************************
  2578. // GetFirstEnvStrLen
  2579. //
  2580. // Purpose: Get the environment string length if it is at the beginning.
  2581. //
  2582. // Parameter: lpStr: Input string
  2583. //
  2584. // Notes: none
  2585. //
  2586. // History: 3/25/2001 geoffguo created
  2587. //*************************************************************
  2588. DWORD GetFirstEnvStrLen (LPTSTR lpStr)
  2589. {
  2590. DWORD dwLen = 0;
  2591. DWORD dwSize, i;
  2592. TCHAR cTemp;
  2593. if (lpStr[0] == L'%')
  2594. {
  2595. dwSize = lstrlen(lpStr);
  2596. for (i = 1; i < dwSize; i++)
  2597. if (lpStr[i] == L'%')
  2598. break;
  2599. if (i < dwSize)
  2600. {
  2601. cTemp = lpStr[i+1];
  2602. lpStr[i+1] = (TCHAR)'\0';
  2603. dwLen = ExpandEnvironmentStrings (lpStr, NULL, 0);
  2604. lpStr[i+1] = cTemp;
  2605. }
  2606. }
  2607. return dwLen;
  2608. }
  2609. //*************************************************************
  2610. // StringValidationCheck
  2611. //
  2612. // Purpose: Check the string to see if it is a valid system path
  2613. //
  2614. // Parameter: lpOriginalStr: Data string to be checked
  2615. // lpSearchStr: Search string
  2616. // lpSysPath: Point to standard system path
  2617. // lpszTailCheck: Point to predefined tail character
  2618. // lpAttrib: Folder attribute
  2619. // dwStrNum: The number of matching string
  2620. //
  2621. // Notes: none
  2622. //
  2623. // History: 3/18/2001 geoffguo created
  2624. //*************************************************************
  2625. BOOL StringValidationCheck (
  2626. LPCTSTR lpOriginalStr,
  2627. LPCTSTR lpSearchStr,
  2628. LPCTSTR lpSysPath,
  2629. LPCTSTR lpTailCheck,
  2630. LPDWORD lpAttrib,
  2631. DWORD dwStrNum)
  2632. {
  2633. BOOL bRet = TRUE;
  2634. DWORD i, dwLen;
  2635. LPTSTR lpOrgStr, lpTemp1, lpTemp2;
  2636. if (lpAttrib == NULL || lpSysPath == NULL)
  2637. goto Exit;
  2638. dwLen = ExpandEnvironmentStrings (lpOriginalStr, NULL, 0);
  2639. if (dwLen == 0)
  2640. {
  2641. bRet = FALSE;
  2642. goto Exit;
  2643. }
  2644. lpOrgStr = calloc (dwLen+1, sizeof(TCHAR));
  2645. if (!lpOrgStr)
  2646. {
  2647. bRet = FALSE;
  2648. goto Exit;
  2649. }
  2650. ExpandEnvironmentStrings (lpOriginalStr, lpOrgStr, dwLen+1);
  2651. dwLen = lstrlen(lpSearchStr);
  2652. //To avoid hit Documents and Settings wrongly,
  2653. //skip the environment variable at the beginning of the string.
  2654. lpTemp1 = lpOrgStr + GetFirstEnvStrLen((LPTSTR)lpOriginalStr);
  2655. for (i = 0; i < dwStrNum; i++)
  2656. {
  2657. lpTemp2 = StrStrI(lpTemp1, lpSearchStr);
  2658. if (!lpTemp2)
  2659. {
  2660. bRet = FALSE;
  2661. goto Exit1;
  2662. }
  2663. lpTemp1 = lpTemp2+dwLen;
  2664. }
  2665. if (*(lpTemp2+dwLen) == *lpTailCheck)
  2666. {
  2667. bRet = FALSE;
  2668. goto Exit1;
  2669. }
  2670. if (StrStrI(lpOriginalStr, L"\\Device\\HarddiskVolume"))
  2671. {
  2672. bRet = TRUE;
  2673. goto Exit1;
  2674. }
  2675. switch (*lpAttrib & 0xffff)
  2676. {
  2677. /*
  2678. CSIDL_DESKTOP // <desktop>
  2679. CSIDL_INTERNET // Internet Explorer (icon on desktop)
  2680. CSIDL_CONTROLS // My Computer\Control Panel
  2681. CSIDL_PRINTERS // My Computer\Printers
  2682. CSIDL_BITBUCKET // <desktop>\Recycle Bin
  2683. CSIDL_MYDOCUMENTS // logical "My Documents" desktop icon
  2684. CSIDL_DRIVES // My Computer
  2685. CSIDL_NETWORK // Network Neighborhood (My Network Places)
  2686. CSIDL_FONTS // windows\fonts
  2687. CSIDL_ALTSTARTUP // non localized startup
  2688. CSIDL_COMMON_ALTSTARTUP // non localized common startup
  2689. CSIDL_WINDOWS // GetWindowsDirectory()
  2690. CSIDL_SYSTEM // GetSystemDirectory()
  2691. CSIDL_CONNECTIONS // Network and Dial-up Connections
  2692. CSIDL_PROFILE // USERPROFILE
  2693. CSIDL_SYSTEMX86 // x86 system directory on RISC
  2694. CSIDL_PROGRAM_FILESX86 // x86 C:\Program Files on RISC
  2695. CSIDL_PROGRAM_FILES_COMMONX86 // x86 Program Files\Common on RISC
  2696. CSIDL_RESOURCES // Resource Direcotry
  2697. CSIDL_RESOURCES_LOCALIZED // Localized Resource Direcotry
  2698. CSIDL_COMMON_OEM_LINKS // Links to All Users OEM specific apps
  2699. CSIDL_COMPUTERSNEARME // Computers Near Me (computered from Workgroup membership)
  2700. */
  2701. case CSIDL_COMMON_APPDATA: // All Users\Application Data
  2702. case CSIDL_COMMON_DESKTOPDIRECTORY: // All Users\Desktop
  2703. case CSIDL_COMMON_STARTMENU: // All Users\Start Menu
  2704. case CSIDL_COMMON_TEMPLATES: // All Users\Templates
  2705. case CSIDL_COMMON_FAVORITES:
  2706. case CSIDL_COMMON_STARTUP: // All Users\Start Menu\Startup
  2707. case CSIDL_COMMON_MUSIC: // All Users\My Music
  2708. case CSIDL_COMMON_PICTURES: // All Users\My Pictures
  2709. case CSIDL_COMMON_VIDEO: // All Users\My Video
  2710. case CSIDL_COMMON_ADMINTOOLS: // All Users\Start Menu\Programs\Administrative Tools
  2711. case CSIDL_COMMON_PROGRAMS: // All Users\Start Menu\Programs
  2712. case CSIDL_COMMON_ACCESSORIES: // All Users\Start Menu\Programs\Accessaries
  2713. case CSIDL_COMMON_DOCUMENTS: // All Users\Documents
  2714. case CSIDL_STARTMENU: // <user name>\Start Menu
  2715. case CSIDL_DESKTOPDIRECTORY: // <user name>\Desktop
  2716. case CSIDL_NETHOOD: // <user name>\nethood
  2717. case CSIDL_TEMPLATES: // <user name>\Templates
  2718. case CSIDL_APPDATA: // <user name>\Application Data
  2719. case CSIDL_LOCAL_SETTINGS: // <user name>\Local Settings
  2720. case CSIDL_PRINTHOOD: // <user name>\PrintHood
  2721. case CSIDL_FAVORITES: // <user name>\Favorites
  2722. case CSIDL_RECENT: // <user name>\Recent
  2723. case CSIDL_SENDTO: // <user name>\SendTo
  2724. case CSIDL_COOKIES: // <user name>\Cookies
  2725. case CSIDL_HISTORY: // <user name>\History
  2726. case CSIDL_PERSONAL: // <user name>\My Documents
  2727. case CSIDL_MYMUSIC: // <user name>\My Document\My Music
  2728. case CSIDL_MYPICTURES: // <user name>\My Document\My Pictures
  2729. case CSIDL_ADMINTOOLS: // <user name>\Start Menu\Programs\Administrative Tools
  2730. case CSIDL_PROGRAMS: // <user name>\Start Menu\Programs
  2731. case CSIDL_STARTUP: // <user name>\Start Menu\Programs\Startup
  2732. case CSIDL_ACCESSORIES: // <user name>\Start Menu\Programs\Accessaries
  2733. case CSIDL_LOCAL_APPDATA: // <user name>\Local Settings\Applicaiton Data (non roaming)
  2734. case CSIDL_INTERNET_CACHE: // <user name>\Local Settings\Temporary Internet Files
  2735. case CSIDL_PROGRAM_FILES_COMMON: // C:\Program Files\Common
  2736. case CSIDL_PF_ACCESSORIES: // C:\Program Files\Accessaries
  2737. case CSIDL_PROGRAM_FILES: // C:\Program Files
  2738. case CSIDL_COMMON_COMMONPROGRAMFILES_SERVICES: //for %CommonProgramFiles%\services
  2739. case CSIDL_COMMON_PROGRAMFILES_ACCESSARIES: //for %ProgramFiles%\accessaries
  2740. case CSIDL_COMMON_PROGRAMFILES_WINNT_ACCESSARIES: //for %ProgramFiles%\Windows NT\accessaries
  2741. case CSIDL_MYVIDEO: // "My Videos" folder
  2742. case CSIDL_CDBURN_AREA: // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
  2743. case CSIDL_COMMON_ACCESSORIES_ACCESSIBILITY:
  2744. case CSIDL_COMMON_ACCESSORIES_ENTERTAINMENT:
  2745. case CSIDL_COMMON_ACCESSORIES_SYSTEM_TOOLS:
  2746. case CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS:
  2747. case CSIDL_COMMON_ACCESSORIES_MS_SCRIPT_DEBUGGER:
  2748. case CSIDL_COMMON_ACCESSORIES_GAMES:
  2749. case CSIDL_COMMON_WINDOWSMEDIA:
  2750. case CSIDL_COMMON_COVERPAGES:
  2751. case CSIDL_COMMON_RECEIVED_FAX:
  2752. case CSIDL_COMMON_SENT_FAX:
  2753. case CSIDL_COMMON_FAX:
  2754. case CSIDL_FAVORITES_LINKS:
  2755. case CSIDL_FAVORITES_MEDIA:
  2756. case CSIDL_ACCESSORIES_ACCESSIBILITY:
  2757. case CSIDL_ACCESSORIES_SYSTEM_TOOLS:
  2758. case CSIDL_ACCESSORIES_ENTERTAINMENT:
  2759. case CSIDL_ACCESSORIES_COMMUNICATIONS:
  2760. case CSIDL_ACCESSORIES_COMMUNICATIONS_HYPERTERMINAL:
  2761. case CSIDL_PROFILES_DIRECTORY:
  2762. case CSIDL_USERNAME_IN_USERPROFILE:
  2763. case CSIDL_UAM_VOLUME:
  2764. case CSIDL_COMMON_SHAREDTOOLS_STATIONERY:
  2765. case CSIDL_NETMEETING_RECEIVED_FILES:
  2766. case CSIDL_COMMON_NETMEETING_RECEIVED_FILES:
  2767. case CSIDL_COMMON_ACCESSORIES_COMMUNICATIONS_FAX:
  2768. case CSIDL_FAX_PERSONAL_COVER_PAGES:
  2769. case CSIDL_FAX:
  2770. bRet = ReverseStrCmp(lpTemp2, lpSysPath);
  2771. break;
  2772. default:
  2773. break;
  2774. }
  2775. Exit1:
  2776. free (lpOrgStr);
  2777. Exit:
  2778. return bRet;
  2779. }
  2780. //*************************************************************
  2781. // ReplaceMultiMatchInString
  2782. //
  2783. // Purpose: Replace the string at multiple place in data string
  2784. //
  2785. // Parameter: lpOldStr: Data string to be checked
  2786. // lpNewStr: Output string buffer
  2787. // cbNewStr: Size of output string buffer
  2788. // dwMaxMatchNum: Max posible match number
  2789. // lpRegStr: String and attribute table
  2790. // bStrCheck: True -- do it, or False -- skip it
  2791. //
  2792. // Notes: none
  2793. //
  2794. // History: 12/10/2001 geoffguo created
  2795. //*************************************************************
  2796. BOOL ReplaceMultiMatchInString(
  2797. LPTSTR lpOldStr,
  2798. LPTSTR lpNewStr,
  2799. size_t cbNewStr,
  2800. DWORD dwMaxMatchNum,
  2801. PREG_STRING_REPLACE lpRegStr,
  2802. LPDWORD pAttrib,
  2803. BOOL bStrCheck)
  2804. {
  2805. BOOL bRet = FALSE;
  2806. LPCTSTR lpSearchStr;
  2807. LPCTSTR lpReplaceStr;
  2808. LPTSTR lpMiddleStr;
  2809. LPCTSTR lpPath;
  2810. LPDWORD lpAttrib;
  2811. TCHAR cNonChar = L'\xFFFF';
  2812. TCHAR cSpaceChar = L' ';
  2813. TCHAR cDotChar = L'.';
  2814. TCHAR cRightChar;
  2815. DWORD cchMiddleStr;
  2816. cchMiddleStr = lstrlen(lpOldStr) + lpRegStr->cchMaxStrLen * dwMaxMatchNum;
  2817. lpMiddleStr = (LPTSTR) calloc(cchMiddleStr, sizeof(TCHAR));
  2818. if (!lpMiddleStr)
  2819. {
  2820. goto Exit;
  2821. }
  2822. if (FAILED(StringCchCopy(lpMiddleStr, cchMiddleStr,lpOldStr)))
  2823. {
  2824. goto Exit;
  2825. }
  2826. lpSearchStr = lpRegStr->lpSearchString;
  2827. lpReplaceStr = lpRegStr->lpReplaceString;
  2828. lpAttrib = lpRegStr->lpAttrib;
  2829. if (lpRegStr->lpFullStringList)
  2830. {
  2831. lpPath = lpRegStr->lpFullStringList;
  2832. }
  2833. else
  2834. {
  2835. lpPath = NULL;
  2836. }
  2837. while (*lpSearchStr && *lpReplaceStr)
  2838. {
  2839. if (bStrCheck)
  2840. {
  2841. if (*lpAttrib == CSIDL_COMMON_DOCUMENTS)
  2842. {
  2843. cRightChar = cSpaceChar;
  2844. } else if (*lpAttrib == CSIDL_USERNAME_IN_USERPROFILE)
  2845. {
  2846. cRightChar = cDotChar;
  2847. }
  2848. else
  2849. {
  2850. cRightChar = cNonChar;
  2851. }
  2852. }
  2853. if(ReplaceString(lpMiddleStr, lpSearchStr, lpReplaceStr, lpNewStr, cchMiddleStr, &cRightChar, lpPath, lpAttrib, bStrCheck))
  2854. {
  2855. if (bStrCheck)
  2856. {
  2857. *pAttrib |= *lpAttrib;
  2858. }
  2859. bRet = TRUE;
  2860. }
  2861. if (FAILED(StringCchCopy(lpMiddleStr, cchMiddleStr,lpNewStr)))
  2862. goto Exit;
  2863. lpSearchStr += lstrlen(lpSearchStr) + 1;
  2864. lpReplaceStr += lstrlen(lpReplaceStr) + 1;
  2865. if (lpPath)
  2866. {
  2867. lpPath += lstrlen(lpPath) + 1;
  2868. }
  2869. if (lpAttrib)
  2870. {
  2871. lpAttrib++;
  2872. }
  2873. }
  2874. Exit:
  2875. if(lpMiddleStr)
  2876. {
  2877. free(lpMiddleStr);
  2878. }
  2879. return bRet;
  2880. }
  2881. //-----------------------------------------------------------------------------
  2882. //
  2883. // Function: ComputeLocalProfileName
  2884. //
  2885. // Synopsis: Constructs the pathname of the local profile for user.
  2886. // It will attempt to create user profile directory using
  2887. // username. If the directory exists, it will append a counter
  2888. // after users name e.g. %documentsettings%\username.001
  2889. //
  2890. // Returns: TRUE if succeeded, FALSE otherwise
  2891. //
  2892. // History: 02/07/2002 Rerkboos Created
  2893. //
  2894. // Notes: none
  2895. //
  2896. //-----------------------------------------------------------------------------
  2897. BOOL ComputeLocalProfileName(
  2898. LPCTSTR lpOldUserName, // Old user name
  2899. LPCTSTR lpNewUserName, // New user name
  2900. LPTSTR lpNewProfilePath, // Output buffer store new profile path
  2901. size_t cchNewProfilePath, // Size of profile path buffer (in WCHAR)
  2902. UINT nRegType // Read the output in REG_SZ or REG_EXPAND_SZ
  2903. )
  2904. {
  2905. HANDLE hFile;
  2906. TCHAR szProfilePath[MAX_PATH];
  2907. TCHAR szUserProfilePath[MAX_PATH];
  2908. TCHAR szExpUserProfilePath[MAX_PATH];
  2909. TCHAR szComputerName[16];
  2910. DWORD cbSize;
  2911. DWORD dwType;
  2912. LONG lRet;
  2913. DWORD cchSize;
  2914. size_t nCounter;
  2915. HKEY hKey;
  2916. HRESULT hr;
  2917. WIN32_FIND_DATA fd;
  2918. if (lpOldUserName == NULL || lpOldUserName[0] == TEXT('\0') ||
  2919. lpNewUserName == NULL || lpNewUserName[0] == TEXT('\0') ||
  2920. lpNewProfilePath == NULL)
  2921. {
  2922. return FALSE;
  2923. }
  2924. //
  2925. // If user name does not change, return the current user's profile path
  2926. //
  2927. if (MyStrCmpI(lpOldUserName, lpNewUserName) == 0)
  2928. {
  2929. hr = GetSetUserProfilePath(lpOldUserName,
  2930. lpNewProfilePath,
  2931. cchNewProfilePath,
  2932. PROFILE_PATH_READ,
  2933. nRegType);
  2934. if (SUCCEEDED(hr))
  2935. {
  2936. return TRUE;
  2937. }
  2938. else
  2939. {
  2940. return FALSE;
  2941. }
  2942. }
  2943. //
  2944. // Get ProfilesDirectory from registry
  2945. //
  2946. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2947. g_cszProfileList,
  2948. 0,
  2949. KEY_READ,
  2950. &hKey)
  2951. == ERROR_SUCCESS)
  2952. {
  2953. cbSize = sizeof(szProfilePath);
  2954. lRet = RegQueryValueEx(hKey,
  2955. PROFILES_DIRECTORY,
  2956. NULL,
  2957. &dwType,
  2958. (LPBYTE) szProfilePath,
  2959. &cbSize);
  2960. RegCloseKey(hKey);
  2961. if (lRet != ERROR_SUCCESS)
  2962. {
  2963. DPF(dlError,
  2964. TEXT("ComputeLocalProfileName: Unable to query reg value <%s>"),
  2965. PROFILES_DIRECTORY);
  2966. return FALSE;
  2967. }
  2968. }
  2969. else
  2970. {
  2971. DPF(dlError,
  2972. TEXT("ComputeLocalProfileName: Unable to open reg key <%s>"),
  2973. g_cszProfileList);
  2974. return FALSE;
  2975. }
  2976. // Compose a new user profile directory
  2977. hr = StringCchPrintf(szUserProfilePath,
  2978. ARRAYSIZE(szUserProfilePath),
  2979. TEXT("%s\\%s"),
  2980. szProfilePath,
  2981. lpNewUserName);
  2982. if ( FAILED(hr) )
  2983. {
  2984. return FALSE;
  2985. }
  2986. // Profile path still contains environment strings, need to expand it
  2987. ExpandEnvironmentStrings(szUserProfilePath,
  2988. szExpUserProfilePath,
  2989. ARRAYSIZE(szExpUserProfilePath));
  2990. // Does this directory exist?
  2991. hFile = FindFirstFile(szExpUserProfilePath, &fd);
  2992. if (INVALID_HANDLE_VALUE == hFile)
  2993. {
  2994. //
  2995. // Directory does not exist, use this name
  2996. //
  2997. hr = StringCchCopy(lpNewProfilePath, cchNewProfilePath, szUserProfilePath);
  2998. if ( FAILED(hr) )
  2999. {
  3000. return FALSE;
  3001. }
  3002. return TRUE;
  3003. }
  3004. else
  3005. {
  3006. //
  3007. // Directory exists, try different name
  3008. //
  3009. FindClose(hFile);
  3010. // Try appending username with computer Name
  3011. cchSize = ARRAYSIZE(szComputerName);
  3012. GetComputerName(szComputerName, &cchSize);
  3013. hr = StringCchPrintf(szUserProfilePath,
  3014. ARRAYSIZE(szUserProfilePath),
  3015. TEXT("%s\\%s.%s"),
  3016. szProfilePath,
  3017. lpNewUserName,
  3018. szComputerName);
  3019. if ( FAILED(hr) )
  3020. {
  3021. return FALSE;
  3022. }
  3023. // Profile path still contains environment strings, need to expand it
  3024. ExpandEnvironmentStrings(szUserProfilePath,
  3025. szExpUserProfilePath,
  3026. ARRAYSIZE(szExpUserProfilePath));
  3027. // Does the new directory name exist?
  3028. hFile = FindFirstFile(szExpUserProfilePath, &fd);
  3029. if (INVALID_HANDLE_VALUE == hFile)
  3030. {
  3031. // Directory does not exist, use this one
  3032. hr = StringCchCopy(lpNewProfilePath, cchNewProfilePath, szUserProfilePath);
  3033. if ( FAILED(hr) )
  3034. {
  3035. return FALSE;
  3036. }
  3037. return TRUE;
  3038. }
  3039. else
  3040. {
  3041. //
  3042. // This directory also exists
  3043. //
  3044. FindClose(hFile);
  3045. for (nCounter = 0 ; nCounter < 1000 ; nCounter++)
  3046. {
  3047. // Try appending counter after user name
  3048. hr = StringCchPrintf(szUserProfilePath,
  3049. ARRAYSIZE(szUserProfilePath),
  3050. TEXT("%s\\%s.%.3d"),
  3051. szProfilePath,
  3052. lpNewUserName,
  3053. nCounter);
  3054. if ( FAILED(hr) )
  3055. {
  3056. return FALSE;
  3057. }
  3058. // Profile path still contains environment strings, need to expand it
  3059. ExpandEnvironmentStrings(szUserProfilePath,
  3060. szExpUserProfilePath,
  3061. ARRAYSIZE(szExpUserProfilePath));
  3062. // Does this directory name exist?
  3063. hFile = FindFirstFile(szExpUserProfilePath, &fd);
  3064. if (INVALID_HANDLE_VALUE == hFile)
  3065. {
  3066. // Directory does not exist, use this one
  3067. hr = StringCchCopy(lpNewProfilePath,
  3068. cchNewProfilePath,
  3069. szUserProfilePath);
  3070. if ( FAILED(hr) )
  3071. {
  3072. return FALSE;
  3073. }
  3074. return TRUE;
  3075. }
  3076. else
  3077. {
  3078. // Directory exists, keep finding...
  3079. FindClose(hFile);
  3080. }
  3081. }
  3082. }
  3083. }
  3084. // If we reach here, we could not find a new profile directory for this user
  3085. return FALSE;
  3086. }
  3087. //-----------------------------------------------------------------------------
  3088. //
  3089. // Function: UpdateProgress
  3090. //
  3091. // Synopsis: Simple progress clock, display the progress during
  3092. // long operation.
  3093. //
  3094. // Returns: none.
  3095. //
  3096. // History: 02/07/2002 Rerkboos Created
  3097. //
  3098. // Notes: none
  3099. //
  3100. //-----------------------------------------------------------------------------
  3101. void UpdateProgress()
  3102. {
  3103. static unsigned short n;
  3104. const TCHAR clock[] = TEXT("-\\|/");
  3105. wprintf(TEXT("%lc\r"), clock[n]);
  3106. n++;
  3107. n %= 4;
  3108. }
  3109. //-----------------------------------------------------------------------//
  3110. //
  3111. // GetMaxStrLen()
  3112. //
  3113. // Get Maximum searching strings and replace strings length for string
  3114. // buffer memery allocation.
  3115. //
  3116. // lpRegStr: Input parameter structure
  3117. //
  3118. // Notes: none
  3119. //
  3120. // History: 12/10/2001 geoffguo created
  3121. //
  3122. //-----------------------------------------------------------------------//
  3123. DWORD GetMaxStrLen (
  3124. PREG_STRING_REPLACE lpRegStr)
  3125. {
  3126. DWORD dwLen = 0;
  3127. DWORD dwMaxLen;
  3128. LPTSTR lpStr;
  3129. lpStr = lpRegStr->lpReplaceString;
  3130. dwMaxLen = 0;
  3131. while (*lpStr)
  3132. {
  3133. dwLen = lstrlen(lpStr);
  3134. //dwMaxLen is the max-length in replacement multi-strings
  3135. if (dwLen > dwMaxLen)
  3136. dwMaxLen = dwLen;
  3137. lpStr += dwLen + 1;
  3138. }
  3139. lpStr = lpRegStr->lpSearchString;
  3140. while (*lpStr)
  3141. {
  3142. dwLen = lstrlen(lpStr);
  3143. //dwMaxLen is the max-length in search and replacement multi-strings
  3144. if (dwLen > dwMaxLen)
  3145. dwMaxLen = dwLen;
  3146. lpStr += dwLen + 1;
  3147. }
  3148. return dwMaxLen;
  3149. }
  3150. //-----------------------------------------------------------------------//
  3151. //
  3152. // AddNodeToList()
  3153. //
  3154. // lpVal: The node needed to add.
  3155. // lpValList: The head of the list.
  3156. //
  3157. // Notes: none
  3158. //
  3159. // History: 12/10/2001 geoffguo created
  3160. //
  3161. //-----------------------------------------------------------------------//
  3162. DWORD AddNodeToList (
  3163. PVALLIST lpVal,
  3164. PVALLIST *lpValList)
  3165. {
  3166. DWORD nResult = ERROR_SUCCESS;
  3167. PVALLIST lpTemp;
  3168. if (!*lpValList)
  3169. {
  3170. *lpValList = lpVal;
  3171. } else
  3172. {
  3173. lpTemp = *lpValList;
  3174. while (lpTemp->pvl_next)
  3175. lpTemp = lpTemp->pvl_next;
  3176. lpTemp->pvl_next = lpVal;
  3177. }
  3178. return nResult;
  3179. }
  3180. //-----------------------------------------------------------------------//
  3181. //
  3182. // RemoveValueList()
  3183. //
  3184. // lpValList: The head of the list.
  3185. //
  3186. // Notes: none
  3187. //
  3188. // History: 12/10/2001 geoffguo created
  3189. //
  3190. //-----------------------------------------------------------------------//
  3191. DWORD RemoveValueList (
  3192. PVALLIST *lpValList)
  3193. {
  3194. DWORD nResult = ERROR_SUCCESS;
  3195. PVALLIST lpTemp, lpDel;
  3196. if (*lpValList)
  3197. {
  3198. lpTemp = *lpValList;
  3199. while (lpTemp)
  3200. {
  3201. lpDel = lpTemp;
  3202. lpTemp = lpTemp->pvl_next;
  3203. if (lpDel->ve.ve_valuename)
  3204. free (lpDel->ve.ve_valuename);
  3205. if (lpDel->ve.ve_valueptr)
  3206. free ((LPBYTE)(lpDel->ve.ve_valueptr));
  3207. if (lpDel->lpPre_valuename)
  3208. free (lpDel->lpPre_valuename);
  3209. free (lpDel);
  3210. }
  3211. }
  3212. return nResult;
  3213. }
  3214. //-----------------------------------------------------------------------//
  3215. //
  3216. // FreeStrList()
  3217. //
  3218. // lpStrList: The head of the list.
  3219. //
  3220. //
  3221. // Notes: none
  3222. //
  3223. // History: 12/10/2001 geoffguo created
  3224. //
  3225. //-----------------------------------------------------------------------//
  3226. void FreeStrList (
  3227. PSTRLIST lpStrList)
  3228. {
  3229. if (lpStrList->pst_next)
  3230. FreeStrList (lpStrList->pst_next);
  3231. if (lpStrList->lpstr)
  3232. free (lpStrList->lpstr);
  3233. free (lpStrList);
  3234. }
  3235. //-----------------------------------------------------------------------//
  3236. //
  3237. // GetMaxMatchNum()
  3238. //
  3239. // Get maximum string match number.
  3240. //
  3241. // lpDataStr: Search string
  3242. // lpRegStr: Input parameter structure
  3243. //
  3244. // Notes: none
  3245. //
  3246. // History: 12/10/2001 geoffguo created
  3247. //
  3248. //-----------------------------------------------------------------------//
  3249. DWORD
  3250. GetMaxMatchNum (
  3251. LPTSTR lpDataStr,
  3252. PREG_STRING_REPLACE lpRegStr)
  3253. {
  3254. DWORD dwMatchNum, dwLen;
  3255. LPTSTR lpTemp;
  3256. LPTSTR lpSearchStr;
  3257. LPTSTR lpFound;
  3258. lpSearchStr = lpRegStr->lpSearchString;
  3259. dwMatchNum = 0;
  3260. while (*lpSearchStr)
  3261. {
  3262. lpTemp = lpDataStr;
  3263. while (lpFound = StrStrI(lpTemp, lpSearchStr))
  3264. {
  3265. dwMatchNum++;
  3266. lpTemp = lpFound + 1;
  3267. }
  3268. dwLen = lstrlen(lpSearchStr);
  3269. lpSearchStr += dwLen + 1;
  3270. }
  3271. return dwMatchNum;
  3272. }
  3273. //-----------------------------------------------------------------------//
  3274. //
  3275. // ReplaceSingleString()
  3276. //
  3277. // DESCRIPTION:
  3278. // Analize a single string and replace localized string to English.
  3279. //
  3280. // lpOldDataStr: String data
  3281. // dwType: Type of string
  3282. // lpRegStr: Input parameter structure
  3283. // lpFullKey: Full sub-key path
  3284. //
  3285. // Notes: none
  3286. //
  3287. // History: 11/10/2001 geoffguo created
  3288. //
  3289. //-----------------------------------------------------------------------//
  3290. LPTSTR ReplaceSingleString (
  3291. LPTSTR lpOldDataStr,
  3292. DWORD dwType,
  3293. PREG_STRING_REPLACE lpRegStr,
  3294. LPTSTR lpFullKey,
  3295. LPDWORD pAttrib,
  3296. BOOL bStrChk)
  3297. {
  3298. DWORD dwMatchNum;
  3299. LPTSTR lpNewDataStr = NULL;
  3300. size_t cbNewDataStr;
  3301. if (!lpOldDataStr)
  3302. goto Exit;
  3303. dwMatchNum = GetMaxMatchNum (lpOldDataStr, lpRegStr);
  3304. if (dwMatchNum > 0)
  3305. {
  3306. if (dwType != REG_DWORD && *lpOldDataStr)
  3307. {
  3308. cbNewDataStr = lstrlen(lpOldDataStr) + lpRegStr->cchMaxStrLen * dwMatchNum;
  3309. lpNewDataStr = (LPTSTR) calloc(cbNewDataStr, sizeof(TCHAR));
  3310. if (!lpNewDataStr)
  3311. {
  3312. DPF (dlError, L"ReplaceSingleString: No enough memory");
  3313. goto Exit;
  3314. }
  3315. if (!ReplaceMultiMatchInString(lpOldDataStr, lpNewDataStr, cbNewDataStr, dwMatchNum, lpRegStr, pAttrib, bStrChk))
  3316. {
  3317. free (lpNewDataStr);
  3318. lpNewDataStr = NULL;
  3319. }
  3320. }
  3321. }
  3322. Exit:
  3323. return lpNewDataStr;
  3324. }
  3325. //-----------------------------------------------------------------------//
  3326. //
  3327. // ReplaceValueSettings()
  3328. //
  3329. // Rename value setting based on input parameter
  3330. //
  3331. // szUserName: User name
  3332. // lpOldDataStr: String value data
  3333. // dwSize: Size of string data
  3334. // lpOldValueName:Value name
  3335. // dwType: Type of string
  3336. // lpRegStr: Input parameter structure
  3337. // lpValList: Updated value list
  3338. // lpFullKey: Full sub-key path
  3339. //
  3340. // Notes: none
  3341. //
  3342. // History: 11/10/2001 geoffguo created
  3343. //
  3344. //-----------------------------------------------------------------------//
  3345. HRESULT ReplaceValueSettings (
  3346. LPTSTR szUserName,
  3347. LPTSTR lpOldDataStr,
  3348. DWORD dwSize,
  3349. LPTSTR lpOldValueName,
  3350. DWORD dwType,
  3351. PREG_STRING_REPLACE lpRegStr,
  3352. PVALLIST *lpValList,
  3353. LPTSTR lpFullKey,
  3354. BOOL bStrChk)
  3355. {
  3356. BOOL bValueName = FALSE;
  3357. BOOL bValueData = FALSE;
  3358. HRESULT hResult = S_OK;
  3359. DWORD dwOutputSize = 0, dwMatchNum = 0;
  3360. LPTSTR lpNewDataStr = NULL;
  3361. LPTSTR lpNewValueName = NULL;
  3362. LPTSTR lpOutputValueName;
  3363. LPTSTR lpEnd;
  3364. LPBYTE lpOutputData;
  3365. PVALLIST lpVal = NULL;
  3366. PSTRLIST lpStrList = NULL;
  3367. PSTRLIST lpLastList = NULL;
  3368. PSTRLIST lpTempList = NULL;
  3369. size_t cbPre_valuename;
  3370. DWORD dwAttrib = 0;
  3371. lpStrList = (PSTRLIST) calloc(sizeof(STRLIST), 1);
  3372. lpLastList = lpStrList;
  3373. if (!lpLastList)
  3374. {
  3375. hResult = E_OUTOFMEMORY;
  3376. DPF (dlError, L"ReplaceValueSettings1: No enough memory");
  3377. goto Exit;
  3378. }
  3379. if ( (dwType & 0xffff)== REG_MULTI_SZ)
  3380. {
  3381. lpEnd = lpOldDataStr;
  3382. while(lpEnd < (lpOldDataStr + dwSize/sizeof(TCHAR)))
  3383. {
  3384. if(*lpEnd == (TCHAR)'\0')
  3385. {
  3386. //empty string
  3387. dwOutputSize += sizeof(TCHAR);
  3388. lpEnd++;
  3389. }
  3390. else
  3391. {
  3392. lpNewDataStr = ReplaceSingleString (
  3393. lpEnd,
  3394. dwType,
  3395. lpRegStr,
  3396. lpFullKey,
  3397. &dwAttrib,
  3398. bStrChk);
  3399. if (lpNewDataStr)
  3400. {
  3401. lpLastList->lpstr = lpNewDataStr;
  3402. bValueData = TRUE;
  3403. }
  3404. else
  3405. {
  3406. size_t cbBufLen = lstrlen(lpEnd)+1;
  3407. lpLastList->lpstr = calloc(cbBufLen, sizeof(TCHAR));
  3408. if (!lpLastList->lpstr)
  3409. {
  3410. hResult = E_OUTOFMEMORY;
  3411. DPF (dlError, L"ReplaceValueSettings2: No enough memory");
  3412. goto Exit;
  3413. }
  3414. hResult = StringCchCopy(lpLastList->lpstr, cbBufLen,lpEnd);
  3415. if (FAILED(hResult))
  3416. {
  3417. DPF (dlError, L"ReplaceValueSettings: buffer too small for %s",lpEnd);
  3418. goto Exit;
  3419. }
  3420. }
  3421. dwOutputSize += (lstrlen(lpLastList->lpstr)+1)*sizeof(TCHAR);
  3422. lpEnd += lstrlen(lpEnd)+1;
  3423. }
  3424. lpLastList->pst_next = (PSTRLIST) calloc(sizeof(STRLIST), 1);
  3425. if (!lpLastList->pst_next)
  3426. {
  3427. hResult = E_OUTOFMEMORY;
  3428. DPF (dlError, L"ReplaceValueSettings3: No enough memory");
  3429. goto Exit;
  3430. }
  3431. lpLastList->pst_next->pst_prev = lpLastList;
  3432. lpLastList = lpLastList->pst_next;
  3433. lpLastList->pst_next = NULL;
  3434. lpLastList->lpstr = NULL;
  3435. }
  3436. if (lpLastList != lpStrList)
  3437. {
  3438. lpLastList = lpLastList->pst_prev;
  3439. free (lpLastList->pst_next);
  3440. lpLastList->pst_next = NULL;
  3441. }
  3442. }
  3443. else
  3444. {
  3445. lpNewDataStr = ReplaceSingleString (
  3446. lpOldDataStr,
  3447. dwType,
  3448. lpRegStr,
  3449. lpFullKey,
  3450. &dwAttrib,
  3451. bStrChk);
  3452. if (lpNewDataStr)
  3453. {
  3454. lpLastList->lpstr = lpNewDataStr;
  3455. bValueData = TRUE;
  3456. }
  3457. else
  3458. {
  3459. lpLastList->lpstr = calloc(dwSize+sizeof(TCHAR), 1);
  3460. if (!lpLastList->lpstr)
  3461. {
  3462. hResult = E_OUTOFMEMORY;
  3463. DPF (dlError, L"ReplaceValueSettings4: No enough memory");
  3464. goto Exit;
  3465. }
  3466. hResult = StringCbCopy(lpLastList->lpstr, dwSize+sizeof(TCHAR), lpOldDataStr);
  3467. if (FAILED(hResult))
  3468. {
  3469. goto Exit;
  3470. }
  3471. }
  3472. lpLastList->pst_next = NULL;
  3473. dwOutputSize = (lstrlen(lpLastList->lpstr)+1)*sizeof(TCHAR);
  3474. }
  3475. if (lpOldValueName)
  3476. dwMatchNum = GetMaxMatchNum (lpOldValueName, lpRegStr);
  3477. else
  3478. dwMatchNum = 0;
  3479. if (dwMatchNum > 0)
  3480. {
  3481. if (*lpOldValueName)
  3482. {
  3483. size_t cbNewValueName = lstrlen(lpOldValueName) + lpRegStr->cchMaxStrLen * dwMatchNum;
  3484. lpNewValueName = (LPTSTR) calloc(cbNewValueName, sizeof(TCHAR));
  3485. if (!lpNewValueName)
  3486. {
  3487. hResult = E_OUTOFMEMORY;
  3488. DPF (dlError, L"ReplaceValueSettings5: No enough memory");
  3489. goto Exit;
  3490. }
  3491. bValueName = ReplaceMultiMatchInString(lpOldValueName, lpNewValueName,cbNewValueName, dwMatchNum, lpRegStr, &dwAttrib, bStrChk);
  3492. }
  3493. }
  3494. if (bValueData || bValueName)
  3495. {
  3496. lpVal = (PVALLIST) calloc(sizeof(VALLIST), 1);
  3497. if (!lpVal)
  3498. {
  3499. hResult = E_OUTOFMEMORY;
  3500. DPF (dlError, L"ReplaceValueSettings6: No enough memory");
  3501. goto Exit;
  3502. }
  3503. if (bValueData)
  3504. {
  3505. lpVal->val_type |= REG_CHANGE_VALUEDATA;
  3506. }
  3507. if (bValueName)
  3508. {
  3509. lpOutputValueName = lpNewValueName;
  3510. lpVal->val_type |= REG_CHANGE_VALUENAME;
  3511. } else
  3512. lpOutputValueName = lpOldValueName;
  3513. if (lpOutputValueName)
  3514. {
  3515. HRESULT hr;
  3516. size_t cbValname = lstrlen(lpOutputValueName) + 1;
  3517. lpVal->ve.ve_valuename = (LPTSTR) calloc(cbValname, sizeof(TCHAR));
  3518. if (!lpVal->ve.ve_valuename)
  3519. {
  3520. hResult = E_OUTOFMEMORY;
  3521. DPF (dlError, L"ReplaceValueSettings7: No enough memory");
  3522. goto Exit;
  3523. }
  3524. //We calculte the buffer for lpVal->lpPre_valuename, so here StringCchCopy should be
  3525. //always success, assinging return value just make prefast happy
  3526. hr = StringCchCopy (lpVal->ve.ve_valuename, cbValname, lpOutputValueName);
  3527. } else
  3528. lpVal->ve.ve_valuename = NULL;
  3529. lpVal->ve.ve_valueptr = (DWORD_PTR) calloc(dwOutputSize, 1);
  3530. if (!lpVal->ve.ve_valueptr)
  3531. {
  3532. free (lpVal->ve.ve_valuename);
  3533. hResult = E_OUTOFMEMORY;
  3534. DPF (dlError, L"ReplaceValueSettings8: No enough memory");
  3535. goto Exit;
  3536. }
  3537. if (lpOldValueName)
  3538. {
  3539. cbPre_valuename = lstrlen(lpOldValueName)+1;
  3540. lpVal->lpPre_valuename = (LPTSTR)calloc(cbPre_valuename, sizeof(TCHAR));
  3541. if (!lpVal->lpPre_valuename)
  3542. {
  3543. free (lpVal->ve.ve_valuename);
  3544. free ((LPBYTE)(lpVal->ve.ve_valueptr));
  3545. hResult = E_OUTOFMEMORY;
  3546. DPF (dlError, L"ReplaceValueSettings9: No enough memory");
  3547. goto Exit;
  3548. }
  3549. } else
  3550. lpVal->lpPre_valuename = NULL;
  3551. lpVal->val_attrib = dwAttrib;
  3552. lpOutputData = (LPBYTE)(lpVal->ve.ve_valueptr);
  3553. lpTempList = lpStrList;
  3554. do {
  3555. if (lpTempList->lpstr)
  3556. memcpy (lpOutputData, (LPBYTE)lpTempList->lpstr, (lstrlen(lpTempList->lpstr)+1)*sizeof(TCHAR));
  3557. else
  3558. {
  3559. lpOutputData[0] = (BYTE)0;
  3560. lpOutputData[1] = (BYTE)0;
  3561. }
  3562. lpOutputData += (lstrlen((LPTSTR)lpOutputData)+1)*sizeof(TCHAR);
  3563. lpTempList = lpTempList->pst_next;
  3564. } while (lpTempList != NULL);
  3565. if (lpOldValueName)
  3566. {
  3567. HRESULT hr;
  3568. //We calculte the buffer for lpVal->lpPre_valuename, so here StringCchCopy should be
  3569. //always success, assinging return value just make prefast happy
  3570. hr = StringCchCopy(lpVal->lpPre_valuename, cbPre_valuename, lpOldValueName);
  3571. }
  3572. lpVal->ve.ve_valuelen = dwOutputSize;
  3573. lpVal->ve.ve_type = dwType;
  3574. lpVal->pvl_next = NULL;
  3575. lpVal->md.dwMDIdentifier = 0x00FFFFFF;
  3576. AddNodeToList(lpVal, lpValList);
  3577. }
  3578. else
  3579. hResult = S_OK;
  3580. Exit:
  3581. if (lpStrList)
  3582. {
  3583. FreeStrList (lpStrList);
  3584. }
  3585. if(lpNewValueName)
  3586. {
  3587. free(lpNewValueName);
  3588. }
  3589. return hResult;
  3590. }
  3591. //-----------------------------------------------------------------------
  3592. //
  3593. // Function: IsAdmin
  3594. //
  3595. // Descrip: Check whether current user is in administrators group
  3596. //
  3597. // Returns: BOOL
  3598. //
  3599. // Notes: none
  3600. //
  3601. // History: 09/17/2001 xiaoz created
  3602. //
  3603. // Notes:
  3604. //
  3605. //-----------------------------------------------------------------------
  3606. BOOL IsAdmin()
  3607. {
  3608. // get the administrator sid
  3609. PSID psidAdministrators;
  3610. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  3611. BOOL bIsAdmin = FALSE;
  3612. if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
  3613. SECURITY_BUILTIN_DOMAIN_RID,
  3614. DOMAIN_ALIAS_RID_ADMINS,
  3615. 0, 0, 0, 0, 0, 0,
  3616. &psidAdministrators))
  3617. {
  3618. return FALSE;
  3619. }
  3620. // on NT5, we should use the CheckTokenMembershipAPI to correctly handle cases where
  3621. // the Adiminstrators group might be disabled. bIsAdmin is BOOL for
  3622. // CheckTokenMembership checks if the SID is enabled in the token. NULL for
  3623. // the token means the token of the current thread. Disabled groups, restricted
  3624. // SIDS, and SE_GROUP_USE_FOR_DENY_ONLY are all considered. If the function
  3625. // returns false, ignore the result.
  3626. if (!CheckTokenMembership(NULL, psidAdministrators, &bIsAdmin))
  3627. {
  3628. bIsAdmin = FALSE;
  3629. }
  3630. FreeSid(psidAdministrators);
  3631. return bIsAdmin;
  3632. }
  3633. //-----------------------------------------------------------------------
  3634. //
  3635. // Function: DoesUserHavePrivilege
  3636. //
  3637. // Descrip:
  3638. //
  3639. // Returns: BOOL
  3640. //
  3641. // Notes: none
  3642. //
  3643. // History: 09/17/2001 xiaoz copied from NTSETUP
  3644. //
  3645. // Routine Description:
  3646. // This routine returns TRUE if the caller's process has
  3647. // the specified privilege. The privilege does not have
  3648. // to be currently enabled. This routine is used to indicate
  3649. // whether the caller has the potential to enable the privilege.
  3650. // Caller is NOT expected to be impersonating anyone and IS
  3651. // expected to be able to open their own process and process
  3652. // token.
  3653. // Arguments:
  3654. // Privilege - the name form of privilege ID (such as
  3655. // SE_SECURITY_NAME).
  3656. //Return Value:
  3657. // TRUE - Caller has the specified privilege.
  3658. // FALSE - Caller does not have the specified privilege.
  3659. BOOL
  3660. DoesUserHavePrivilege(
  3661. PTSTR PrivilegeName
  3662. )
  3663. {
  3664. HANDLE Token;
  3665. ULONG BytesRequired;
  3666. PTOKEN_PRIVILEGES Privileges;
  3667. BOOL b;
  3668. DWORD i;
  3669. LUID Luid;
  3670. //
  3671. // Open the process token.
  3672. //
  3673. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) {
  3674. return(FALSE);
  3675. }
  3676. b = FALSE;
  3677. Privileges = NULL;
  3678. //
  3679. // Get privilege information.
  3680. //
  3681. if(!GetTokenInformation(Token,TokenPrivileges,NULL,0,&BytesRequired)
  3682. && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  3683. && (Privileges = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR,BytesRequired))
  3684. && GetTokenInformation(Token,TokenPrivileges,Privileges,BytesRequired,&BytesRequired)
  3685. && LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) {
  3686. //
  3687. // See if we have the requested privilege
  3688. //
  3689. for(i=0; i<Privileges->PrivilegeCount; i++) {
  3690. if(!memcmp(&Luid,&Privileges->Privileges[i].Luid,sizeof(LUID))) {
  3691. b = TRUE;
  3692. break;
  3693. }
  3694. }
  3695. }
  3696. //
  3697. // Clean up and return.
  3698. //
  3699. if(Privileges) {
  3700. LocalFree((HLOCAL)Privileges);
  3701. }
  3702. CloseHandle(Token);
  3703. return(b);
  3704. }
  3705. //-----------------------------------------------------------------------
  3706. //
  3707. // Function: EnablePrivilege
  3708. //
  3709. // Descrip:
  3710. //
  3711. // Returns: BOOL
  3712. //
  3713. // Notes: none
  3714. //
  3715. // History: 09/17/2001 xiaoz copied from NTSETUP
  3716. //
  3717. // Notes:
  3718. //
  3719. //-----------------------------------------------------------------------
  3720. BOOL
  3721. EnablePrivilege(
  3722. IN PTSTR PrivilegeName,
  3723. IN BOOL Enable
  3724. )
  3725. {
  3726. HANDLE Token;
  3727. BOOL b;
  3728. TOKEN_PRIVILEGES NewPrivileges;
  3729. LUID Luid;
  3730. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) {
  3731. return(FALSE);
  3732. }
  3733. if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) {
  3734. CloseHandle(Token);
  3735. return(FALSE);
  3736. }
  3737. NewPrivileges.PrivilegeCount = 1;
  3738. NewPrivileges.Privileges[0].Luid = Luid;
  3739. NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
  3740. b = AdjustTokenPrivileges(
  3741. Token,
  3742. FALSE,
  3743. &NewPrivileges,
  3744. 0,
  3745. NULL,
  3746. NULL
  3747. );
  3748. CloseHandle(Token);
  3749. return(b);
  3750. }
  3751. //-----------------------------------------------------------------------
  3752. //
  3753. // Function: GetCurrentControlSet
  3754. //
  3755. // Descrip:
  3756. //
  3757. // Returns: INT
  3758. //
  3759. // Notes: none
  3760. //
  3761. // History: 09/17/2001 xiaoz created
  3762. //
  3763. // Notes: the HKLM\SYSTEM\CurrentControlSet is actually is copy of
  3764. // HKLM\SYSTEM\ControlSetXXX, the XXX is specified in
  3765. // HKLM\SYSTEM\Select\Current . This API returns this XXX,
  3766. // if it failed , it returns -1
  3767. //
  3768. //-----------------------------------------------------------------------
  3769. INT GetCurrentControlSet()
  3770. {
  3771. DWORD dwErr;
  3772. DWORD dwCurrrent,dwSize;
  3773. HKEY hKey = NULL;
  3774. dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  3775. TEXT("SYSTEM\\Select"),
  3776. 0,
  3777. KEY_READ,
  3778. &hKey );
  3779. // if failed to open registry key , return -1
  3780. if( dwErr != ERROR_SUCCESS )
  3781. {
  3782. dwCurrrent = -1;
  3783. hKey = NULL;
  3784. goto Cleanup;
  3785. }
  3786. dwSize = sizeof(DWORD);
  3787. dwErr = RegQueryValueEx(hKey,
  3788. TEXT("Current"),
  3789. NULL, //reserved
  3790. NULL, //type
  3791. (LPBYTE) &dwCurrrent,
  3792. &dwSize );
  3793. if(dwErr != ERROR_SUCCESS)
  3794. {
  3795. dwCurrrent = -1;
  3796. goto Cleanup;
  3797. }
  3798. //Notes:here we succeeded in geting the value, do we need to do
  3799. //a registry open to make sure the actual HKLM\SYSTEM\ControlSetXXX
  3800. //is there
  3801. Cleanup:
  3802. if (hKey)
  3803. {
  3804. RegCloseKey(hKey);
  3805. }
  3806. return dwCurrrent;
  3807. }
  3808. //-----------------------------------------------------------------------
  3809. //
  3810. // Function: ReplaceCurrentControlSet
  3811. //
  3812. // Descrip:
  3813. //
  3814. // Returns: BOOL
  3815. //
  3816. // Notes: none
  3817. //
  3818. // History: 09/17/2001 xiaoz created
  3819. //
  3820. // Notes: replace CurrentControlSet with ControlSetXXX
  3821. //
  3822. //-----------------------------------------------------------------------
  3823. HRESULT ReplaceCurrentControlSet(LPTSTR strList)
  3824. {
  3825. INT nCurrent;
  3826. TCHAR szCurrCrtlSet[MAX_PATH];
  3827. DWORD dwStrLen;
  3828. TCHAR *lpTmpBuf;
  3829. HRESULT hr;
  3830. //If the string list is empty .we just return
  3831. dwStrLen = MultiSzLen(strList);
  3832. if (dwStrLen < 3)
  3833. {
  3834. return S_OK;
  3835. }
  3836. //If there is no CurrentControlSet in the String list, just return
  3837. if (!MultiSzSubStr (TEXT("CurrentControlSet"),strList))
  3838. {
  3839. return S_FALSE;
  3840. }
  3841. //Get the CurrentControlSet #, this is specified in registry , detail see GetCurrentControlSet
  3842. nCurrent = GetCurrentControlSet();
  3843. // if we can not get, just bail out
  3844. if (nCurrent < 0)
  3845. {
  3846. return HRESULT_FROM_WIN32(GetLastError());
  3847. }
  3848. //This indeed will never fail, unless this registry value has been tamnpered,
  3849. // we will bail out then
  3850. if (FAILED(hr = StringCchPrintf(szCurrCrtlSet,MAX_PATH,TEXT("ControlSet%03d\0"),nCurrent)))
  3851. {
  3852. return hr;
  3853. }
  3854. //Get a Temp buffer for saving replaced string, dwStrLen already includes the last NULL
  3855. // in this multi-sz string
  3856. lpTmpBuf = malloc( dwStrLen * sizeof(TCHAR) );
  3857. if (!lpTmpBuf)
  3858. {
  3859. return E_OUTOFMEMORY;
  3860. }
  3861. memmove((BYTE*)lpTmpBuf,(BYTE*)strList,dwStrLen * sizeof(TCHAR));
  3862. hr = StringMultipleReplacement(lpTmpBuf,TEXT("CurrentControlSet\0"),szCurrCrtlSet,strList,dwStrLen);
  3863. if (FAILED(hr))
  3864. {
  3865. memmove(strList,lpTmpBuf,dwStrLen * sizeof(TCHAR));
  3866. }
  3867. free(lpTmpBuf);
  3868. return hr;
  3869. }
  3870. //-----------------------------------------------------------------------
  3871. //
  3872. // Function: UnProtectSFPFiles
  3873. //
  3874. // Descrip:
  3875. //
  3876. // Returns: DWORD
  3877. //
  3878. // Notes: none
  3879. //
  3880. // History: 09/17/2001 xiaoz created
  3881. //
  3882. // Notes: Unprotect a list of files specified by multiSzFileList which
  3883. // is multi-sz string. pdwResult is an array of DWORD which will
  3884. // be specifed whether success or failure of each unprotect action
  3885. // if can be NULL if called does not care this information.
  3886. // the retuan value is BOOL,if is FALSE, it means starting SFP
  3887. // service failed.
  3888. //
  3889. //-----------------------------------------------------------------------
  3890. BOOL UnProtectSFPFiles(
  3891. IN LPTSTR multiSzFileList,
  3892. IN OUT LPDWORD pdwResult)
  3893. {
  3894. HANDLE hSfp = INVALID_HANDLE_VALUE;
  3895. DWORD bResult = TRUE;
  3896. LPTSTR lp;
  3897. LPDWORD lpdw;
  3898. DWORD dw;
  3899. //If the no string there, we just return success
  3900. if (!multiSzFileList)
  3901. {
  3902. goto Cleanup;
  3903. }
  3904. //Connect to SFP service
  3905. hSfp = SfcConnectToServer( NULL );
  3906. if (INVALID_HANDLE_VALUE == hSfp)
  3907. {
  3908. bResult = FALSE;
  3909. goto Cleanup;
  3910. }
  3911. //lp points to Path while lpdw points to the result array
  3912. lp = multiSzFileList;
  3913. lpdw = pdwResult;
  3914. while (*lp)
  3915. {
  3916. DWORD dwResult = NO_ERROR;
  3917. //if the file pointed by lp is in the file protection list
  3918. // unprotect it and put the return value to array
  3919. if (SfcIsFileProtected(hSfp,lp))
  3920. {
  3921. dwResult = SfcFileException(hSfp,lp, SFC_ACTION_ADDED | SFC_ACTION_REMOVED | SFC_ACTION_MODIFIED
  3922. | SFC_ACTION_RENAMED_OLD_NAME |SFC_ACTION_RENAMED_NEW_NAME);
  3923. }
  3924. else
  3925. {
  3926. dw = GetLastError();
  3927. }
  3928. if (lpdw)
  3929. {
  3930. *lpdw = dwResult;
  3931. lpdw++;
  3932. }
  3933. lp = lp + lstrlen(lp) + 1;
  3934. }
  3935. Cleanup:
  3936. if (hSfp)
  3937. {
  3938. SfcClose(hSfp);
  3939. }
  3940. return bResult;
  3941. }
  3942. /*++
  3943. Routine Description:
  3944. This routine returns TRUE if the caller's process has
  3945. the specified privilege. The privilege does not have
  3946. to be currently enabled. This routine is used to indicate
  3947. whether the caller has the potential to enable the privilege.
  3948. Caller is NOT expected to be impersonating anyone and IS
  3949. expected to be able to open their own process and process
  3950. token.
  3951. Arguments:
  3952. lpDir - the direcory which is to be backuped
  3953. lpBackupDir - the backup directory name we got , it should be %lpDir%.CLMTxxx
  3954. - where xxx is 000,001,...
  3955. cChBackupDir is the lpBackupDir's size in TCHAR
  3956. bFindExist - if this is TRUE , it means the lpDir has already been backuiped
  3957. - and caller wants to get that dir name
  3958. - if this is FALSE , it means the caller want to find an appriate backup
  3959. - dir name for lpDir
  3960. Return Value:
  3961. TRUE - The directory name found.
  3962. FALSE - The directory can not be found
  3963. --*/
  3964. BOOL GetBackupDir(
  3965. LPCTSTR lpDir,
  3966. LPTSTR lpBackupDir,
  3967. size_t cChBackupDir,
  3968. BOOL bFindExist)
  3969. {
  3970. BOOL bResult = FALSE;
  3971. HRESULT hr;
  3972. int nCounter;
  3973. HANDLE hFile;
  3974. WIN32_FIND_DATA fd;
  3975. if (!lpDir && !lpDir[0])
  3976. {
  3977. goto Exit;
  3978. }
  3979. if (!lpBackupDir)
  3980. {
  3981. goto Exit;
  3982. }
  3983. for (nCounter = 0 ; nCounter < 1000 ; nCounter++)
  3984. {
  3985. // Try appending counter after
  3986. TCHAR szCounter[10];
  3987. _itot(nCounter,szCounter,10);
  3988. hr = StringCchPrintf(lpBackupDir,cChBackupDir,
  3989. TEXT("%s.%s%03s"),lpDir,TEXT("clmt"),szCounter);
  3990. if ( FAILED(hr) )
  3991. {
  3992. goto Exit;
  3993. }
  3994. // Does this directory name exist?
  3995. hFile = FindFirstFile(lpBackupDir, &fd);
  3996. if (INVALID_HANDLE_VALUE == hFile)
  3997. {
  3998. // Directory does not exist, use this one
  3999. FindClose(hFile);
  4000. break;
  4001. }
  4002. else
  4003. { // Directory exists, keep finding...
  4004. FindClose(hFile);
  4005. }
  4006. }//end of for nCounter
  4007. if (nCounter < 1000)
  4008. {
  4009. //we found a dir name that does not exist
  4010. if (bFindExist)
  4011. {
  4012. if (nCounter > 0)
  4013. {
  4014. TCHAR szCounter[10];
  4015. nCounter--;
  4016. _itot(nCounter,szCounter,10);
  4017. hr = StringCchPrintf(lpBackupDir,cChBackupDir,
  4018. TEXT("%s.%s%03s"),lpDir,TEXT("clmt"),szCounter);
  4019. if ( FAILED(hr) )
  4020. {
  4021. goto Exit;
  4022. }
  4023. }
  4024. else
  4025. {
  4026. goto Exit;
  4027. }
  4028. }
  4029. bResult = TRUE;
  4030. }
  4031. Exit:
  4032. return (bResult);
  4033. }
  4034. //Add an entry in INF file for key rename
  4035. //szOldKeyPath --- the key needs to be renamed
  4036. //szNewKeyPath --- to name to be renamed to
  4037. //szUsername --- if it's HKLM, HKCR, this needs to be NULL
  4038. // ---- otherwise it's the username for registry
  4039. HRESULT AddRegKeyRename(
  4040. LPTSTR lpszKeyRoot,
  4041. LPTSTR lpszOldKeyname,
  4042. LPTSTR lpszNewKeyname,
  4043. LPTSTR szUsername)
  4044. {
  4045. TCHAR *lpszOneLine =NULL;
  4046. TCHAR *lpszSectionName = NULL;
  4047. DWORD cchOneLine;
  4048. DWORD cchSectionNameLen;
  4049. HRESULT hr;
  4050. TCHAR szIndex[MAX_PATH];
  4051. LPTSTR lpUserStringSid = NULL;
  4052. PSID pSid = NULL;
  4053. LPTSTR lpszKeyRootWithoutBackSlash = lpszKeyRoot;
  4054. LPTSTR lpszKeyRootWithoutBackSlash1 = NULL,lpszOldKeyname1 = NULL,lpszNewKeyname1 = NULL;
  4055. if ( !lpszKeyRoot || !lpszOldKeyname || !lpszNewKeyname)
  4056. {
  4057. hr = E_INVALIDARG;
  4058. goto Cleanup;
  4059. }
  4060. cchOneLine = lstrlen(lpszKeyRoot)+lstrlen(lpszOldKeyname)+lstrlen(lpszNewKeyname)+MAX_PATH;
  4061. if (szUsername)
  4062. {
  4063. cchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4064. }
  4065. else
  4066. {
  4067. cchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4068. }
  4069. lpszOneLine = malloc(cchOneLine*sizeof(TCHAR));
  4070. lpszSectionName = malloc(cchSectionNameLen*sizeof(TCHAR));
  4071. if (!lpszOneLine || !lpszSectionName)
  4072. {
  4073. hr = E_OUTOFMEMORY;
  4074. goto Cleanup;
  4075. }
  4076. if (lpszKeyRoot[0]==TEXT('\\'))
  4077. {
  4078. lpszKeyRootWithoutBackSlash = lpszKeyRoot + 1;
  4079. }
  4080. if (!szUsername ||!MyStrCmpI(szUsername,TEXT("System")))
  4081. {
  4082. hr = StringCchCopy(lpszSectionName,cchSectionNameLen,REG_PERSYS_UPDATE);
  4083. if (FAILED(hr))
  4084. {
  4085. goto Cleanup;
  4086. }
  4087. }
  4088. else
  4089. {
  4090. if (!MyStrCmpI(szUsername,DEFAULT_USER)
  4091. ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE))
  4092. {
  4093. hr = StringCchPrintf(lpszSectionName,cchSectionNameLen,TEXT("%s%s"),
  4094. REG_PERUSER_UPDATE_PREFIX,szUsername);
  4095. if (FAILED(hr))
  4096. {
  4097. goto Cleanup;
  4098. }
  4099. }
  4100. else
  4101. {
  4102. hr = GetSIDFromName(szUsername,&pSid);
  4103. if (FAILED(hr))
  4104. {
  4105. goto Cleanup;
  4106. }
  4107. if (!ConvertSidToStringSid(pSid,&lpUserStringSid))
  4108. {
  4109. lpUserStringSid = NULL;
  4110. hr = HRESULT_FROM_WIN32(GetLastError());
  4111. goto Cleanup;
  4112. }
  4113. if (cchSectionNameLen < (DWORD)(lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)
  4114. + lstrlen(REG_PERSYS_UPDATE)))
  4115. {
  4116. LPTSTR pTmp;
  4117. cchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)
  4118. + lstrlen(REG_PERSYS_UPDATE);
  4119. pTmp = realloc(lpszSectionName,cchSectionNameLen*sizeof(TCHAR));
  4120. if (!pTmp)
  4121. {
  4122. hr = E_OUTOFMEMORY;
  4123. goto Cleanup;
  4124. }
  4125. else
  4126. {
  4127. lpszSectionName = pTmp;
  4128. }
  4129. }
  4130. hr = StringCchPrintf(lpszSectionName,cchSectionNameLen,TEXT("%s%s"),
  4131. REG_PERUSER_UPDATE_PREFIX,lpUserStringSid);
  4132. if (FAILED(hr))
  4133. {
  4134. goto Cleanup;
  4135. }
  4136. }
  4137. }
  4138. AddExtraQuoteEtc(lpszKeyRootWithoutBackSlash,&lpszKeyRootWithoutBackSlash1);
  4139. AddExtraQuoteEtc(lpszOldKeyname,&lpszOldKeyname1);
  4140. AddExtraQuoteEtc(lpszNewKeyname,&lpszNewKeyname1);
  4141. hr = StringCchPrintf(lpszOneLine,cchOneLine,TEXT("%d,\"%s\",\"%s\",\"%s\""),
  4142. CONSTANT_REG_KEY_RENAME,lpszKeyRootWithoutBackSlash1,
  4143. lpszOldKeyname1,lpszNewKeyname1);
  4144. if (FAILED(hr))
  4145. {
  4146. goto Cleanup;
  4147. }
  4148. g_dwKeyIndex++;
  4149. _itot(g_dwKeyIndex,szIndex,16);
  4150. if (!WritePrivateProfileString(lpszSectionName,szIndex,lpszOneLine,g_szToDoINFFileName))
  4151. {
  4152. hr = HRESULT_FROM_WIN32(GetLastError());
  4153. }
  4154. else
  4155. {
  4156. hr = S_OK;
  4157. }
  4158. Cleanup:
  4159. FreePointer(lpszOneLine);
  4160. FreePointer(lpszSectionName);
  4161. FreePointer(lpszKeyRootWithoutBackSlash1);
  4162. FreePointer(lpszOldKeyname1);
  4163. FreePointer(lpszNewKeyname1);
  4164. if (lpUserStringSid)
  4165. {
  4166. LocalFree(lpUserStringSid);
  4167. }
  4168. FreePointer(pSid);
  4169. return (hr);
  4170. }
  4171. HRESULT SetSectionName (
  4172. LPTSTR szUsername,
  4173. LPTSTR *lpszSectionName)
  4174. {
  4175. HRESULT hr;
  4176. PSID pSid = NULL;
  4177. LPTSTR lpUserStringSid = NULL;
  4178. DWORD dwCchSectionNameLen;
  4179. if (szUsername)
  4180. {
  4181. dwCchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4182. }
  4183. else
  4184. {
  4185. dwCchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4186. }
  4187. *lpszSectionName = malloc(dwCchSectionNameLen*sizeof(TCHAR));
  4188. if (!*lpszSectionName)
  4189. {
  4190. hr = E_OUTOFMEMORY;
  4191. goto Cleanup;
  4192. }
  4193. if (!szUsername
  4194. ||!MyStrCmpI(szUsername,TEXT("System")))
  4195. {
  4196. //We calculte the buffer for lpszSectionName, so here StringCchCopy should be
  4197. //always success, assinging return value just make prefast happy
  4198. hr = StringCchCopy(*lpszSectionName,dwCchSectionNameLen,REG_PERSYS_UPDATE);
  4199. }
  4200. else
  4201. {
  4202. if (!MyStrCmpI(szUsername,DEFAULT_USER)
  4203. ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE))
  4204. {
  4205. hr = StringCchPrintf(*lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"),
  4206. REG_PERUSER_UPDATE_PREFIX,szUsername);
  4207. if (FAILED(hr))
  4208. {
  4209. goto Cleanup;
  4210. }
  4211. }
  4212. else
  4213. {
  4214. LPTSTR pTmp;
  4215. hr = GetSIDFromName(szUsername,&pSid);
  4216. if (FAILED(hr))
  4217. {
  4218. goto Cleanup;
  4219. }
  4220. if (!ConvertSidToStringSid(pSid,&lpUserStringSid))
  4221. {
  4222. lpUserStringSid = NULL;
  4223. hr = HRESULT_FROM_WIN32(GetLastError());
  4224. goto Cleanup;
  4225. }
  4226. dwCchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4227. pTmp = realloc(*lpszSectionName,dwCchSectionNameLen*sizeof(TCHAR));
  4228. if (!pTmp)
  4229. {
  4230. hr = E_OUTOFMEMORY;
  4231. goto Cleanup;
  4232. }
  4233. else
  4234. {
  4235. *lpszSectionName = pTmp;
  4236. }
  4237. hr = StringCchPrintf(*lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"),
  4238. REG_PERUSER_UPDATE_PREFIX,lpUserStringSid);
  4239. if (FAILED(hr))
  4240. {
  4241. goto Cleanup;
  4242. }
  4243. }
  4244. }
  4245. Cleanup:
  4246. if (lpUserStringSid)
  4247. {
  4248. LocalFree(lpUserStringSid);
  4249. }
  4250. if (FAILED(hr))
  4251. FreePointer(*lpszSectionName);
  4252. FreePointer(pSid);
  4253. return hr;
  4254. }
  4255. //Add an entry in INF file for Value rename
  4256. //szKeyPath: Key path
  4257. //szOldValueName: Old value name
  4258. //szNewValueName: New value name. Set to NULL if value name is not changed.
  4259. //szOldValueData: Old value data. Set to NULL if value data is not changed.
  4260. //szNewValueData: New value data. Set to NULL if value data is not changed.
  4261. //dwType: Date type REG_SZ,REG_EXPAND_SZ,REG_MULTI_SZ
  4262. //dwAttrib: Value string attribute
  4263. //szUsername: If it's HKLM, HKCR, this needs to be NULL
  4264. // otherwise it's the username for registry
  4265. HRESULT AddRegValueRename(
  4266. LPTSTR szKeyPath,
  4267. LPTSTR szOldValueName,
  4268. LPTSTR szNewValueName,
  4269. LPTSTR szOldValueData,
  4270. LPTSTR szNewValueData,
  4271. DWORD dwType,
  4272. DWORD dwAttrib,
  4273. LPTSTR szUsername)
  4274. {
  4275. HRESULT hr;
  4276. TCHAR *szRenameValueDataLine = NULL;
  4277. TCHAR *szRenameValueNameLine = NULL;
  4278. DWORD dwCchsizeforRenameValueData;
  4279. DWORD dwCchsizeforRenameValueName = MAX_PATH ;
  4280. TCHAR *lpszSectionName = NULL;
  4281. DWORD dwCchSectionNameLen;
  4282. TCHAR szIndex[MAX_PATH];
  4283. LPTSTR lpUserStringSid = NULL;
  4284. PSID pSid = NULL;
  4285. LPTSTR lpszKeyPathWithoutBackSlash = NULL,lpszKeyPathWithoutBackSlash1 = NULL;
  4286. LPTSTR lpszOldNameWithExtraQuote = NULL, lpszNewNameWithExtraQuote = NULL;
  4287. LPTSTR lpszValueDataExtraQuote = NULL;
  4288. if (szUsername)
  4289. {
  4290. dwCchSectionNameLen = lstrlen(szUsername)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4291. }
  4292. else
  4293. {
  4294. dwCchSectionNameLen = lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4295. }
  4296. lpszSectionName = malloc(dwCchSectionNameLen*sizeof(TCHAR));
  4297. if (!lpszSectionName)
  4298. {
  4299. hr = E_OUTOFMEMORY;
  4300. goto Cleanup;
  4301. }
  4302. if (!szUsername
  4303. ||!MyStrCmpI(szUsername,TEXT("System")))
  4304. {
  4305. lpszKeyPathWithoutBackSlash = szKeyPath;
  4306. //We calculte the buffer for lpszSectionName, so here StringCchCopy should be
  4307. //always success, assinging return value just make prefast happy
  4308. hr = StringCchCopy(lpszSectionName,dwCchSectionNameLen,REG_PERSYS_UPDATE);
  4309. }
  4310. else
  4311. {
  4312. if (szKeyPath[0]==TEXT('\\'))
  4313. {
  4314. lpszKeyPathWithoutBackSlash = szKeyPath + 1;
  4315. }
  4316. else
  4317. {
  4318. lpszKeyPathWithoutBackSlash = szKeyPath;
  4319. }
  4320. if (!MyStrCmpI(szUsername,DEFAULT_USER)
  4321. ||!MyStrCmpI(szUsername,APPLICATION_DATA_METABASE))
  4322. {
  4323. hr = StringCchPrintf(lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"),
  4324. REG_PERUSER_UPDATE_PREFIX,szUsername);
  4325. if (FAILED(hr))
  4326. {
  4327. goto Cleanup;
  4328. }
  4329. }
  4330. else
  4331. {
  4332. LPTSTR pTmp;
  4333. hr = GetSIDFromName(szUsername,&pSid);
  4334. if (FAILED(hr))
  4335. {
  4336. goto Cleanup;
  4337. }
  4338. if (!ConvertSidToStringSid(pSid,&lpUserStringSid))
  4339. {
  4340. lpUserStringSid = NULL;
  4341. hr = HRESULT_FROM_WIN32(GetLastError());
  4342. goto Cleanup;
  4343. }
  4344. dwCchSectionNameLen = lstrlen(lpUserStringSid)+lstrlen(REG_PERUSER_UPDATE_PREFIX)+ lstrlen(REG_PERSYS_UPDATE);
  4345. pTmp = realloc(lpszSectionName,dwCchSectionNameLen*sizeof(TCHAR));
  4346. if (!pTmp)
  4347. {
  4348. hr = E_OUTOFMEMORY;
  4349. goto Cleanup;
  4350. }
  4351. else
  4352. {
  4353. lpszSectionName = pTmp;
  4354. }
  4355. hr = StringCchPrintf(lpszSectionName,dwCchSectionNameLen,TEXT("%s%s"),
  4356. REG_PERUSER_UPDATE_PREFIX,lpUserStringSid);
  4357. if (FAILED(hr))
  4358. {
  4359. goto Cleanup;
  4360. }
  4361. }
  4362. }
  4363. hr = AddExtraQuoteEtc(lpszKeyPathWithoutBackSlash,&lpszKeyPathWithoutBackSlash1);
  4364. if (FAILED(hr))
  4365. {
  4366. goto Cleanup;
  4367. }
  4368. hr = AddExtraQuoteEtc(szOldValueName,&lpszOldNameWithExtraQuote);
  4369. if (FAILED(hr))
  4370. {
  4371. goto Cleanup;
  4372. }
  4373. if (szNewValueData)
  4374. {
  4375. if ((dwType & 0xffff) == REG_MULTI_SZ)
  4376. {
  4377. LPTSTR lpString = NULL;
  4378. hr = MultiSZ2String(szNewValueData,TEXT(','),&lpString);
  4379. if (FAILED(hr))
  4380. {
  4381. goto Cleanup;
  4382. }
  4383. dwCchsizeforRenameValueData = lstrlen(lpszKeyPathWithoutBackSlash1) +
  4384. lstrlen(szOldValueName) +
  4385. lstrlen(lpString) + MAX_PATH;
  4386. szRenameValueDataLine = malloc(dwCchsizeforRenameValueData*sizeof(TCHAR));
  4387. if (!szRenameValueDataLine)
  4388. {
  4389. hr = E_OUTOFMEMORY;
  4390. FreePointer(lpString);
  4391. goto Cleanup;
  4392. }
  4393. hr = StringCchPrintf(szRenameValueDataLine,dwCchsizeforRenameValueData,
  4394. TEXT("%d,%d,\"%s\",\"%s\",%s"),CONSTANT_REG_VALUE_DATA_RENAME,
  4395. dwType,lpszKeyPathWithoutBackSlash1,szOldValueName,lpString);
  4396. FreePointer(lpString);
  4397. if (FAILED(hr))
  4398. {
  4399. goto Cleanup;
  4400. }
  4401. }
  4402. else
  4403. {
  4404. hr = AddExtraQuoteEtc(szNewValueData,&lpszValueDataExtraQuote);
  4405. if (FAILED(hr))
  4406. {
  4407. goto Cleanup;
  4408. }
  4409. dwCchsizeforRenameValueData = lstrlen(lpszKeyPathWithoutBackSlash1) +
  4410. lstrlen(szOldValueName) +
  4411. lstrlen(lpszValueDataExtraQuote) + MAX_PATH;
  4412. szRenameValueDataLine = malloc(dwCchsizeforRenameValueData*sizeof(TCHAR));
  4413. if (!szRenameValueDataLine)
  4414. {
  4415. hr = E_OUTOFMEMORY;
  4416. goto Cleanup;
  4417. }
  4418. hr = StringCchPrintf(szRenameValueDataLine,dwCchsizeforRenameValueData,
  4419. TEXT("%d,%u,\"%s\",\"%s\",\"%s\""), CONSTANT_REG_VALUE_DATA_RENAME,
  4420. dwType,lpszKeyPathWithoutBackSlash1,lpszOldNameWithExtraQuote, lpszValueDataExtraQuote);
  4421. if (FAILED(hr))
  4422. {
  4423. goto Cleanup;
  4424. }
  4425. }
  4426. g_dwKeyIndex++;
  4427. _itot(g_dwKeyIndex,szIndex,16);
  4428. if (!WritePrivateProfileString(lpszSectionName,szIndex,szRenameValueDataLine,g_szToDoINFFileName))
  4429. {
  4430. hr = HRESULT_FROM_WIN32(GetLastError());
  4431. goto Cleanup;
  4432. }
  4433. }
  4434. if (szNewValueName)
  4435. {
  4436. hr = AddExtraQuoteEtc(szNewValueName,&lpszNewNameWithExtraQuote);
  4437. if (FAILED(hr))
  4438. {
  4439. goto Cleanup;
  4440. }
  4441. dwCchsizeforRenameValueName = lstrlen(lpszKeyPathWithoutBackSlash1) +
  4442. lstrlen(lpszOldNameWithExtraQuote) +
  4443. lstrlen(lpszNewNameWithExtraQuote) + MAX_PATH;
  4444. szRenameValueNameLine = malloc(dwCchsizeforRenameValueName*sizeof(TCHAR));
  4445. if (!szRenameValueNameLine)
  4446. {
  4447. hr = E_OUTOFMEMORY;
  4448. goto Cleanup;
  4449. }
  4450. hr = StringCchPrintf(szRenameValueNameLine,dwCchsizeforRenameValueName,TEXT("%d,\"%s\",\"%s\",\"%s\""),
  4451. CONSTANT_REG_VALUE_NAME_RENAME,lpszKeyPathWithoutBackSlash1,
  4452. lpszOldNameWithExtraQuote,lpszNewNameWithExtraQuote);
  4453. if (FAILED(hr))
  4454. {
  4455. goto Cleanup;
  4456. }
  4457. g_dwKeyIndex++;
  4458. _itot(g_dwKeyIndex,szIndex,16);
  4459. if (!WritePrivateProfileString(lpszSectionName,szIndex,szRenameValueNameLine,g_szToDoINFFileName))
  4460. {
  4461. hr = HRESULT_FROM_WIN32(GetLastError());
  4462. goto Cleanup;
  4463. }
  4464. }
  4465. hr = S_OK;
  4466. Cleanup:
  4467. if (lpUserStringSid)
  4468. {
  4469. LocalFree(lpUserStringSid);
  4470. }
  4471. FreePointer(lpszOldNameWithExtraQuote);
  4472. FreePointer(lpszNewNameWithExtraQuote);
  4473. FreePointer(lpszValueDataExtraQuote);
  4474. FreePointer(szRenameValueDataLine);
  4475. FreePointer(szRenameValueNameLine);
  4476. FreePointer(lpszSectionName);
  4477. FreePointer(pSid);
  4478. FreePointer(lpszKeyPathWithoutBackSlash1);
  4479. return (hr);
  4480. }
  4481. HRESULT AddFolderRename(
  4482. LPTSTR szOldName,
  4483. LPTSTR szNewName,
  4484. DWORD dwType,
  4485. LPTSTR lpExcludeList)
  4486. {
  4487. LPTSTR szSectionName = TEXT("Folder.ObjectRename");
  4488. LPTSTR szOneLine = NULL;
  4489. size_t CchOneLine = MAX_PATH;
  4490. TCHAR szIndex[MAX_PATH];
  4491. HRESULT hr;
  4492. LPTSTR lpString = NULL;
  4493. switch (dwType)
  4494. {
  4495. case TYPE_DIR_MOVE:
  4496. if (lpExcludeList)
  4497. {
  4498. hr = MultiSZ2String(lpExcludeList,TEXT(','),&lpString);
  4499. if (FAILED(hr))
  4500. {
  4501. goto Cleanup;
  4502. }
  4503. CchOneLine +=lstrlen(lpString)+lstrlen(szOldName)+lstrlen(szNewName);
  4504. szOneLine = malloc(CchOneLine * sizeof(TCHAR));
  4505. if (!szOneLine)
  4506. {
  4507. hr = E_OUTOFMEMORY;
  4508. goto Cleanup;
  4509. }
  4510. hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%d,\"%s\",\"%s\",%s"),
  4511. dwType,szOldName,szNewName,lpString);
  4512. free(lpString);
  4513. if (FAILED(hr))
  4514. {
  4515. goto Cleanup;
  4516. }
  4517. break;
  4518. }
  4519. else
  4520. {
  4521. }
  4522. case TYPE_SFPFILE_MOVE:
  4523. case TYPE_FILE_MOVE:
  4524. CchOneLine += lstrlen(szOldName)+lstrlen(szNewName);
  4525. szOneLine = malloc(CchOneLine * sizeof(TCHAR));
  4526. if (!szOneLine)
  4527. {
  4528. hr = E_OUTOFMEMORY;
  4529. goto Cleanup;
  4530. }
  4531. hr = StringCchPrintf(szOneLine,CchOneLine,TEXT("%d,\"%s\",\"%s\""),dwType,szOldName,szNewName);
  4532. if (FAILED(hr))
  4533. {
  4534. goto Cleanup;
  4535. }
  4536. break;
  4537. }
  4538. g_dwKeyIndex++;
  4539. _itot(g_dwKeyIndex,szIndex,16);
  4540. if (!WritePrivateProfileString(szSectionName,szIndex,szOneLine,g_szToDoINFFileName))
  4541. {
  4542. hr = HRESULT_FROM_WIN32(GetLastError());
  4543. goto Cleanup;
  4544. }
  4545. // Add the file/folder rename to Change log
  4546. // Does not care about return value
  4547. hr = AddFileChangeLog(dwType, szOldName, szNewName);
  4548. hr = S_OK;
  4549. Cleanup:
  4550. if (szOneLine)
  4551. {
  4552. free(szOneLine);
  4553. }
  4554. if (lpString)
  4555. {
  4556. free(lpString);
  4557. }
  4558. return hr;
  4559. }
  4560. LONG EnsureCLMTReg()
  4561. {
  4562. HKEY hkey = NULL;
  4563. LONG lStatus;
  4564. lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey);
  4565. if (lStatus == ERROR_SUCCESS)
  4566. {
  4567. RegCloseKey(hkey);
  4568. }
  4569. return lStatus;
  4570. }
  4571. HRESULT SaveInstallLocale(void)
  4572. {
  4573. HKEY hkey = NULL;
  4574. LONG lStatus;
  4575. HRESULT hr;
  4576. LCID lcid;
  4577. TCHAR szLocale[MAX_PATH];
  4578. TCHAR szStr[16];
  4579. lcid = GetInstallLocale();
  4580. if (!lcid)
  4581. {
  4582. hr = HRESULT_FROM_WIN32(GetLastError());
  4583. goto Exit;
  4584. }
  4585. if (!IsValidLocale(lcid,LCID_INSTALLED))
  4586. {
  4587. hr = E_FAIL;
  4588. goto Exit;
  4589. }
  4590. _itot(lcid,szStr,16);
  4591. //StringCchCopy should be always success, since we called IsValidLocale to make sure
  4592. //it is a valid locale which should be less than MAX_PATH chars
  4593. hr = StringCchPrintf(szLocale,ARRAYSIZE(szLocale),TEXT("%08s"),szStr);
  4594. lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey);
  4595. if (lStatus != ERROR_SUCCESS)
  4596. {
  4597. hr = HRESULT_FROM_WIN32(lStatus);
  4598. goto Exit;
  4599. }
  4600. lStatus = RegSetValueEx(hkey,
  4601. CLMT_OriginalInstallLocale,
  4602. 0, //reserved
  4603. REG_SZ,//type
  4604. (LPBYTE) szLocale,
  4605. (lstrlen(szLocale)+1)*sizeof(TCHAR));
  4606. if( lStatus != ERROR_SUCCESS )
  4607. {
  4608. hr = HRESULT_FROM_WIN32(lStatus);
  4609. goto Exit;
  4610. }
  4611. hr = S_OK;
  4612. Exit:
  4613. if (hkey)
  4614. {
  4615. RegCloseKey(hkey);
  4616. }
  4617. return hr;
  4618. }
  4619. HRESULT GetSavedInstallLocale(LCID *plcid)
  4620. {
  4621. HKEY hkey = NULL;
  4622. LONG lStatus;
  4623. HRESULT hr;
  4624. LCID lcid;
  4625. TCHAR szLocale[MAX_PATH];
  4626. TCHAR *pStop;
  4627. DWORD dwSize;
  4628. if ( !plcid )
  4629. {
  4630. hr = E_INVALIDARG;
  4631. goto Exit;
  4632. }
  4633. lStatus = RegOpenKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey);
  4634. if (lStatus != ERROR_SUCCESS)
  4635. {
  4636. hr = HRESULT_FROM_WIN32(lStatus);
  4637. goto Exit;
  4638. }
  4639. dwSize = MAX_PATH *sizeof(TCHAR);
  4640. lStatus = RegQueryValueEx(hkey,
  4641. CLMT_OriginalInstallLocale,
  4642. NULL, //reserved
  4643. NULL,//type
  4644. (LPBYTE) szLocale,
  4645. &dwSize);
  4646. if( lStatus != ERROR_SUCCESS )
  4647. {
  4648. hr = HRESULT_FROM_WIN32(lStatus);
  4649. goto Exit;
  4650. }
  4651. *plcid = _tcstol(szLocale, &pStop, 16);
  4652. if (!IsValidLocale(*plcid,LCID_INSTALLED))
  4653. {
  4654. hr = E_FAIL;
  4655. goto Exit;
  4656. }
  4657. hr = S_OK;
  4658. Exit:
  4659. if (hkey)
  4660. {
  4661. RegCloseKey(hkey);
  4662. }
  4663. return hr;
  4664. }
  4665. HRESULT SetCLMTStatus(DWORD dwRunStatus)
  4666. {
  4667. HKEY hkey = NULL;
  4668. LONG lStatus;
  4669. HRESULT hr;
  4670. if ( (dwRunStatus != CLMT_DOMIG)
  4671. && (dwRunStatus != CLMT_UNDO_PROGRAM_FILES)
  4672. && (dwRunStatus != CLMT_UNDO_APPLICATION_DATA)
  4673. && (dwRunStatus != CLMT_UNDO_ALL)
  4674. && (dwRunStatus != CLMT_DOMIG_DONE)
  4675. && (dwRunStatus != CLMT_UNDO_PROGRAM_FILES_DONE)
  4676. && (dwRunStatus != CLMT_UNDO_APPLICATION_DATA_DONE)
  4677. && (dwRunStatus != CLMT_UNDO_ALL_DONE)
  4678. && (dwRunStatus != CLMT_CURE_PROGRAM_FILES)
  4679. && (dwRunStatus != CLMT_CLEANUP_AFTER_UPGRADE) )
  4680. {
  4681. hr = E_INVALIDARG;
  4682. goto Exit;
  4683. }
  4684. lStatus = RegCreateKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey);
  4685. if (lStatus != ERROR_SUCCESS)
  4686. {
  4687. hr = HRESULT_FROM_WIN32(lStatus);
  4688. goto Exit;
  4689. }
  4690. lStatus = RegSetValueEx(hkey,
  4691. CLMT_RUNNING_STATUS,
  4692. 0, //reserved
  4693. REG_DWORD,//type
  4694. (LPBYTE) &dwRunStatus,
  4695. sizeof(DWORD));
  4696. if( lStatus != ERROR_SUCCESS )
  4697. {
  4698. hr = HRESULT_FROM_WIN32(lStatus);
  4699. goto Exit;
  4700. }
  4701. hr = S_OK;
  4702. Exit:
  4703. if (hkey)
  4704. {
  4705. RegCloseKey(hkey);
  4706. }
  4707. return hr;
  4708. }
  4709. HRESULT GetCLMTStatus(PDWORD pdwRunStatus)
  4710. {
  4711. HKEY hkey = NULL;
  4712. LONG lStatus;
  4713. HRESULT hr;
  4714. DWORD dwSize;
  4715. if ( !pdwRunStatus )
  4716. {
  4717. hr = E_INVALIDARG;
  4718. goto Exit;
  4719. }
  4720. lStatus = RegOpenKey(HKEY_LOCAL_MACHINE,CLMT_REGROOT,&hkey);
  4721. if (lStatus != ERROR_SUCCESS)
  4722. {
  4723. hr = HRESULT_FROM_WIN32(lStatus);
  4724. goto Exit;
  4725. }
  4726. dwSize = sizeof(DWORD);
  4727. lStatus = RegQueryValueEx(hkey,
  4728. CLMT_RUNNING_STATUS,
  4729. NULL,
  4730. NULL,
  4731. (LPBYTE)pdwRunStatus,
  4732. &dwSize);
  4733. if( lStatus != ERROR_SUCCESS )
  4734. {
  4735. hr = HRESULT_FROM_WIN32(lStatus);
  4736. goto Exit;
  4737. }
  4738. hr = S_OK;
  4739. Exit:
  4740. if (hkey)
  4741. {
  4742. RegCloseKey(hkey);
  4743. }
  4744. return hr;
  4745. }
  4746. //-----------------------------------------------------------------------
  4747. //
  4748. // Function: GetInstallLocale
  4749. //
  4750. // Descrip: Get the OS installed locale
  4751. //
  4752. // Returns: LCID
  4753. //
  4754. // Notes: if fails, the return value is 0, otherwize is the os 's lcid
  4755. //
  4756. // History: 09/17/2001 xiaoz created
  4757. //
  4758. // Notes: If it returns 0, it means failure, and call GetLastError() to get the detail
  4759. // error code
  4760. //
  4761. //-----------------------------------------------------------------------
  4762. UINT GetInstallLocale(VOID)
  4763. {
  4764. LONG dwErr;
  4765. HKEY hkey;
  4766. DWORD dwSize;
  4767. TCHAR buffer[512];
  4768. LANGID rcLang;
  4769. UINT lcid;
  4770. lcid = 0;
  4771. dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  4772. TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\Language"),
  4773. 0,
  4774. KEY_READ,
  4775. &hkey );
  4776. if( dwErr == ERROR_SUCCESS )
  4777. {
  4778. dwSize = sizeof(buffer);
  4779. dwErr = RegQueryValueEx(hkey,
  4780. TEXT("InstallLanguage"),
  4781. NULL, //reserved
  4782. NULL, //type
  4783. (LPBYTE) buffer,
  4784. &dwSize );
  4785. if(dwErr == ERROR_SUCCESS)
  4786. {
  4787. lcid = StrToUInt(buffer);
  4788. }
  4789. RegCloseKey(hkey);
  4790. }
  4791. return( lcid );
  4792. }
  4793. //-----------------------------------------------------------------------
  4794. //
  4795. // Function: SetInstallLocale
  4796. //
  4797. // Descrip: Set the OS installed locale
  4798. //
  4799. // Returns: HRESULT
  4800. //
  4801. // Notes:
  4802. //
  4803. // History: 09/17/2001 xiaoz created
  4804. //
  4805. //
  4806. //-----------------------------------------------------------------------
  4807. HRESULT SetInstallLocale(LCID lcid)
  4808. {
  4809. LONG dwErr;
  4810. HKEY hkey = NULL;
  4811. TCHAR szLocale[32],szTmpLocale[32];
  4812. HRESULT hr;
  4813. if (!IsValidLocale(lcid,LCID_INSTALLED))
  4814. {
  4815. hr = E_INVALIDARG;
  4816. goto Exit;
  4817. }
  4818. dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  4819. TEXT("SYSTEM\\CurrentControlSet\\Control\\Nls\\Language"),
  4820. 0,
  4821. KEY_WRITE,
  4822. &hkey );
  4823. if( dwErr != ERROR_SUCCESS )
  4824. {
  4825. hr = HRESULT_FROM_WIN32(dwErr);
  4826. goto Exit;
  4827. }
  4828. //following 2 sentences should never fail since we already validated by IsValidLocale
  4829. _itot(lcid,szTmpLocale,16);
  4830. //StringCchCopy should be always success, since we called IsValidLocale to make sure
  4831. //it is a valid locale which should be less than 32 chars
  4832. hr = StringCchPrintf(szLocale,ARRAYSIZE(szLocale),TEXT("%04s"),szTmpLocale);
  4833. dwErr = RegSetValueEx(hkey,
  4834. TEXT("InstallLanguage"),
  4835. 0, //reserved
  4836. REG_SZ,//type
  4837. (LPBYTE) szLocale,
  4838. (lstrlen(szLocale)+1)*sizeof(TCHAR));
  4839. if( dwErr != ERROR_SUCCESS )
  4840. {
  4841. hr = HRESULT_FROM_WIN32(dwErr);
  4842. goto Exit;
  4843. }
  4844. hr = S_OK;
  4845. Exit:
  4846. if (hkey)
  4847. {
  4848. RegCloseKey(hkey);
  4849. }
  4850. return hr;
  4851. }
  4852. //
  4853. // Function: ReverseStrCmp
  4854. //
  4855. // Description: Reverse compare strings
  4856. //
  4857. // Returns: TRUE if two strings are equal.
  4858. // FALSE if different.
  4859. // Notes:
  4860. //
  4861. // History: 3/14/2002 geoffguo created
  4862. //
  4863. BOOL ReverseStrCmp(
  4864. LPCTSTR lpCurrentChar,
  4865. LPCTSTR lpStrBuf)
  4866. {
  4867. BOOL bRet = FALSE;
  4868. DWORD i, dwLen;
  4869. LPCTSTR lpStr1, lpStr2;
  4870. if (!lpCurrentChar || !lpStrBuf)
  4871. goto Exit;
  4872. dwLen = lstrlen(lpStrBuf);
  4873. do
  4874. {
  4875. bRet = TRUE;
  4876. lpStr1 = lpCurrentChar;
  4877. lpStr2 = &lpStrBuf[dwLen-1];
  4878. for (i = 0; i < dwLen; i++)
  4879. {
  4880. if (IsBadStringPtr(lpStr1, 1) || *lpStr1 == (TCHAR)'\0' ||
  4881. towupper(*lpStr1) != towupper(*lpStr2) &&
  4882. *lpStr2 != L':' && //solve MS Installer path issue: G?\Program Files
  4883. *lpStr2 != L'\\') //solve MS FrontPage URL format issue: D:/Document and Settings
  4884. {
  4885. bRet = FALSE;
  4886. break;
  4887. }
  4888. lpStr1--;
  4889. lpStr2--;
  4890. }
  4891. if (bRet)
  4892. break;
  4893. dwLen--;
  4894. } while (lpStrBuf[dwLen-1] != (TCHAR)'\\' && dwLen > 0);
  4895. Exit:
  4896. return bRet;
  4897. }
  4898. DWORD MultiSZNumOfString(IN LPTSTR lpMultiSZ)
  4899. {
  4900. DWORD dwNum = 0;
  4901. LPTSTR lpStr = lpMultiSZ;
  4902. if (!lpMultiSZ)
  4903. {
  4904. return 0;
  4905. }
  4906. while (*lpStr)
  4907. {
  4908. dwNum++;
  4909. lpStr = lpStr + lstrlen(lpStr)+1;
  4910. }
  4911. return dwNum;
  4912. }
  4913. //
  4914. // Function: StrNumInMultiSZ
  4915. //
  4916. // Description: Get string number in multi-string
  4917. //
  4918. // Returns: String number or 0xFFFFFFFF if not find.
  4919. //
  4920. // Notes:
  4921. //
  4922. // History: 3/21/2002 geoffguo created
  4923. //
  4924. DWORD StrNumInMultiSZ(
  4925. LPCTSTR lpStr,
  4926. LPCTSTR lpMultiSZ)
  4927. {
  4928. DWORD dwNum = 0xFFFFFFFF;
  4929. LPTSTR lpTemp;
  4930. if (!lpMultiSZ || !lpStr)
  4931. {
  4932. goto Exit;
  4933. }
  4934. lpTemp = (LPTSTR)lpMultiSZ;
  4935. dwNum = 0;
  4936. while (*lpTemp)
  4937. {
  4938. if(MyStrCmpI(lpStr, lpTemp) == 0)
  4939. break;
  4940. dwNum++;
  4941. lpTemp = lpTemp + lstrlen(lpTemp)+1;
  4942. }
  4943. if (*lpTemp == (TCHAR)NULL)
  4944. dwNum = 0xFFFFFFFF;
  4945. Exit:
  4946. return dwNum;
  4947. }
  4948. //
  4949. // Function: GetStrInMultiSZ
  4950. //
  4951. // Description: Get string in multi-string based on string number.
  4952. //
  4953. // Returns: Point to the string or NULL.
  4954. //
  4955. // Notes:
  4956. //
  4957. // History: 3/21/2002 geoffguo created
  4958. //
  4959. LPTSTR GetStrInMultiSZ(
  4960. DWORD dwNum,
  4961. LPCTSTR lpMultiSZ)
  4962. {
  4963. DWORD i;
  4964. LPTSTR lpTemp = NULL;
  4965. if (!lpMultiSZ)
  4966. {
  4967. goto Exit;
  4968. }
  4969. lpTemp = (LPTSTR)lpMultiSZ;
  4970. i = 0;
  4971. while (*lpTemp)
  4972. {
  4973. if(i == dwNum)
  4974. break;
  4975. i++;
  4976. lpTemp = lpTemp + lstrlen(lpTemp)+1;
  4977. }
  4978. if (*lpTemp == (TCHAR)NULL)
  4979. lpTemp = NULL;
  4980. Exit:
  4981. return lpTemp;
  4982. }
  4983. HRESULT MultiSZ2String(
  4984. IN LPTSTR lpMultiSZ,
  4985. IN TCHAR chSeperator,
  4986. OUT LPTSTR *lpString)
  4987. {
  4988. LPTSTR lpSource = NULL,lpDest = NULL,lpDestStart = NULL,lpTmpBuf = NULL;
  4989. DWORD cchLen ;
  4990. HRESULT hr;
  4991. DWORD dwNumofStringInMSZ;
  4992. if (!lpMultiSZ || !lpString )
  4993. {
  4994. hr = E_INVALIDARG;
  4995. goto Cleanup;
  4996. }
  4997. cchLen = MultiSzLen(lpMultiSZ);
  4998. if (cchLen < 3)
  4999. {
  5000. hr = E_INVALIDARG;
  5001. *lpString = NULL;
  5002. goto Cleanup;
  5003. }
  5004. dwNumofStringInMSZ = MultiSZNumOfString(lpMultiSZ);
  5005. lpDest = malloc( (cchLen + dwNumofStringInMSZ * 2) * sizeof(TCHAR));
  5006. lpDestStart = lpDest;
  5007. lpTmpBuf = malloc( (cchLen + dwNumofStringInMSZ * 2) * sizeof(TCHAR));
  5008. if (!lpDest || !lpTmpBuf)
  5009. {
  5010. hr = E_OUTOFMEMORY;
  5011. goto Cleanup;
  5012. }
  5013. lpSource = lpMultiSZ;
  5014. while (*lpSource)
  5015. {
  5016. //We calculte the buffer for lpTmpBuf, so here StringCchCopy should be
  5017. //always success, assinging return value just make prefast happy
  5018. hr = StringCchPrintf(lpTmpBuf,cchLen + dwNumofStringInMSZ * 2,TEXT("\"%s\""),lpSource);
  5019. memcpy((BYTE*)lpDest,(BYTE*)lpTmpBuf,lstrlen(lpTmpBuf) * sizeof(TCHAR));
  5020. lpSource = lpSource + lstrlen(lpSource)+1;
  5021. lpDest = lpDest + lstrlen(lpTmpBuf);
  5022. *lpDest = chSeperator;
  5023. lpDest++;
  5024. }
  5025. lpDest--;
  5026. *lpDest = TEXT('\0');
  5027. hr = S_OK;
  5028. Cleanup:
  5029. if (lpTmpBuf)
  5030. {
  5031. free(lpTmpBuf);
  5032. }
  5033. if FAILED(hr)
  5034. {
  5035. if (lpDestStart)
  5036. {
  5037. free(lpDestStart);
  5038. }
  5039. lpDestStart = NULL;
  5040. }
  5041. *lpString = lpDestStart;
  5042. return hr;
  5043. }
  5044. void FreePointer(void *lp)
  5045. {
  5046. if (lp)
  5047. {
  5048. free(lp);
  5049. }
  5050. }
  5051. HRESULT GetSIDFromName(
  5052. IN LPTSTR lpszUserName,
  5053. OUT PSID *ppSid)
  5054. {
  5055. PSID pSid = NULL;
  5056. DWORD cbSid = 1024;
  5057. SID_NAME_USE Use ;
  5058. HRESULT hr;
  5059. DWORD dwDomainNameLen = MAX_PATH;
  5060. TCHAR szDomain[MAX_PATH];
  5061. if (!lpszUserName)
  5062. {
  5063. hr = E_INVALIDARG;
  5064. goto Cleanup;
  5065. }
  5066. pSid = (PSID)malloc( cbSid);
  5067. if(!pSid)
  5068. {
  5069. hr = E_OUTOFMEMORY;
  5070. goto Cleanup;
  5071. }
  5072. if (LookupAccountName(NULL,lpszUserName,pSid,&cbSid,szDomain,&dwDomainNameLen,&Use)== FALSE)
  5073. {
  5074. DWORD dwErr = GetLastError();
  5075. if(dwErr != ERROR_INSUFFICIENT_BUFFER)
  5076. {
  5077. hr = HRESULT_FROM_WIN32(dwErr);
  5078. goto Cleanup;
  5079. }
  5080. else
  5081. {
  5082. free(pSid);
  5083. pSid = (PSID)malloc( cbSid);
  5084. if(!pSid)
  5085. {
  5086. hr = E_OUTOFMEMORY;
  5087. goto Cleanup;
  5088. }
  5089. dwDomainNameLen = MAX_PATH;
  5090. if (LookupAccountName(NULL,lpszUserName,pSid,&cbSid,szDomain,&dwDomainNameLen,&Use)== FALSE)
  5091. {
  5092. hr = HRESULT_FROM_WIN32(GetLastError());
  5093. goto Cleanup;
  5094. }
  5095. }
  5096. }
  5097. //Check the SID
  5098. if(!IsValidSid(pSid))
  5099. {
  5100. hr = E_FAIL;
  5101. goto Cleanup;
  5102. }
  5103. hr = S_OK;
  5104. Cleanup:
  5105. if FAILED(hr)
  5106. {
  5107. if (pSid)
  5108. {
  5109. free(pSid);
  5110. }
  5111. *ppSid = NULL;
  5112. }
  5113. else
  5114. {
  5115. *ppSid = pSid;
  5116. }
  5117. return hr;
  5118. }
  5119. void BoostMyPriority()
  5120. {
  5121. HANDLE hProcess;
  5122. hProcess = GetCurrentProcess();
  5123. SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS);
  5124. }
  5125. //***************************************************************************
  5126. //
  5127. // BOOL StopService
  5128. //
  5129. // DESCRIPTION:
  5130. //
  5131. // Stops and then removes the service.
  5132. //
  5133. // PARAMETERS:
  5134. //
  5135. // pServiceName short service name
  5136. // dwMaxWait max time in seconds to wait
  5137. //
  5138. // RETURN VALUE:
  5139. //
  5140. // TRUE if it worked
  5141. //
  5142. //***************************************************************************
  5143. BOOL StopService(
  5144. IN LPCTSTR pServiceName,
  5145. IN DWORD dwMaxWait)
  5146. {
  5147. BOOL bRet = FALSE;
  5148. SC_HANDLE schService;
  5149. SC_HANDLE schSCManager;
  5150. DWORD dwCnt;
  5151. SERVICE_STATUS ssStatus; // current status of the service
  5152. schSCManager = OpenSCManager(
  5153. NULL, // machine (NULL == local)
  5154. NULL, // database (NULL == default)
  5155. SC_MANAGER_ALL_ACCESS // access required
  5156. );
  5157. if ( schSCManager )
  5158. {
  5159. schService = OpenService(schSCManager, pServiceName, SERVICE_ALL_ACCESS);
  5160. if (schService)
  5161. {
  5162. // try to stop the service
  5163. if ( bRet = ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
  5164. {
  5165. for(dwCnt=0; dwCnt < dwMaxWait &&
  5166. QueryServiceStatus( schService, &ssStatus ); dwCnt++)
  5167. {
  5168. if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
  5169. Sleep( 1000 );
  5170. else
  5171. break;
  5172. }
  5173. }
  5174. CloseServiceHandle(schService);
  5175. }
  5176. CloseServiceHandle(schSCManager);
  5177. }
  5178. return bRet;
  5179. }
  5180. //***************************************************************************
  5181. //
  5182. // HRESULT ReconfigureServiceStartType
  5183. //
  5184. // DESCRIPTION:
  5185. //
  5186. // Change the Service Start Type, there are following type availabe now
  5187. // SERVICE_AUTO_START
  5188. // SERVICE_BOOT_START
  5189. // SERVICE_DEMAND_START
  5190. // SERVICE_DISABLED
  5191. // SERVICE_SYSTEM_START
  5192. //
  5193. // PARAMETERS:
  5194. //
  5195. // pServiceName short service name
  5196. // dwOldType service current start type
  5197. // dwNewType start type you want to change to
  5198. // dwMaxWait max time in seconds to wait
  5199. //
  5200. // RETURN VALUE: S_OK if change successfully
  5201. //
  5202. // Note: if current start type is dwOldType, the function will try to
  5203. // change start type to dwNewType.
  5204. // if current start type is NOT dwOldType, it will not do any
  5205. // change, in this S_FALSE is returned.
  5206. // If you want change service start type to dwNewType, no mater
  5207. // current start type, specify dwOldType >=0xFFFF
  5208. //
  5209. //***************************************************************************
  5210. HRESULT ReconfigureServiceStartType(
  5211. IN LPCTSTR pServiceName,
  5212. IN DWORD dwOldType,
  5213. IN DWORD dwNewType,
  5214. IN DWORD dwMaxWait)
  5215. {
  5216. SC_LOCK sclLock = NULL;
  5217. SERVICE_DESCRIPTION sdBuf;
  5218. DWORD dwBytesNeeded, dwStartType;
  5219. SC_HANDLE schSCManager = NULL;
  5220. SC_HANDLE schService = NULL;
  5221. DWORD dwErr = ERROR_SUCCESS;
  5222. LPQUERY_SERVICE_CONFIG lpqscBuf = NULL;
  5223. HRESULT hr = S_OK;
  5224. DWORD dwCnt;
  5225. schSCManager = OpenSCManager(
  5226. NULL, // machine (NULL == local)
  5227. NULL, // database (NULL == default)
  5228. SC_MANAGER_ALL_ACCESS // access required
  5229. );
  5230. if (!schSCManager)
  5231. {
  5232. dwErr = GetLastError();
  5233. goto cleanup;
  5234. }
  5235. // Need to acquire database lock before reconfiguring.
  5236. for(dwCnt=0; dwCnt < dwMaxWait ; dwCnt++)
  5237. {
  5238. sclLock = LockServiceDatabase(schSCManager);
  5239. if (sclLock == NULL)
  5240. {
  5241. // Exit if the database is not locked by another process.
  5242. dwErr = GetLastError();
  5243. if (dwErr != ERROR_SERVICE_DATABASE_LOCKED)
  5244. {
  5245. goto cleanup;
  5246. }
  5247. else
  5248. {
  5249. Sleep(1000);
  5250. }
  5251. }
  5252. else
  5253. {
  5254. break;
  5255. }
  5256. }
  5257. if (!sclLock)
  5258. {
  5259. goto cleanup;
  5260. }
  5261. // The database is locked, so it is safe to make changes.
  5262. // Open a handle to the service.
  5263. schService = OpenService(
  5264. schSCManager, // SCManager database
  5265. pServiceName, // name of service
  5266. SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG ); // need CHANGE access
  5267. if (schService == NULL)
  5268. {
  5269. dwErr = GetLastError();
  5270. goto cleanup;
  5271. }
  5272. lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
  5273. if (lpqscBuf == NULL)
  5274. {
  5275. dwErr = ERROR_OUTOFMEMORY;
  5276. goto cleanup;
  5277. }
  5278. if (!QueryServiceConfig(schService, // handle to service
  5279. lpqscBuf, // buffer
  5280. 4096, // size of buffer
  5281. &dwBytesNeeded))
  5282. {
  5283. dwErr = GetLastError();
  5284. goto cleanup;
  5285. }
  5286. if (dwOldType < 0xFFFF)
  5287. {
  5288. if (lpqscBuf->dwStartType != dwOldType)
  5289. {
  5290. hr = S_FALSE;
  5291. goto cleanup;
  5292. }
  5293. }
  5294. // Make the changes.
  5295. if (! ChangeServiceConfig(schService, // handle of service
  5296. SERVICE_NO_CHANGE, // service type: no change
  5297. dwNewType, // change service start type
  5298. SERVICE_NO_CHANGE, // error control: no change
  5299. NULL, // binary path: no change
  5300. NULL, // load order group: no change
  5301. NULL, // tag ID: no change
  5302. NULL, // dependencies: no change
  5303. NULL, // account name: no change
  5304. NULL, // password: no change
  5305. NULL) ) // display name: no change
  5306. {
  5307. dwErr = GetLastError();
  5308. goto cleanup;
  5309. }
  5310. hr = S_OK;
  5311. cleanup:
  5312. if (dwErr != ERROR_SUCCESS)
  5313. {
  5314. hr = HRESULT_FROM_WIN32(dwErr);
  5315. }
  5316. if (sclLock)
  5317. {
  5318. UnlockServiceDatabase(sclLock);
  5319. }
  5320. if (schService)
  5321. { // Close the handle to the service.
  5322. CloseServiceHandle(schService);
  5323. }
  5324. if (schSCManager)
  5325. {
  5326. CloseServiceHandle(schSCManager);
  5327. }
  5328. if (lpqscBuf)
  5329. {
  5330. LocalFree(lpqscBuf);
  5331. }
  5332. return hr;
  5333. }
  5334. //-----------------------------------------------------------------------
  5335. //
  5336. // Function: MyGetShortPathName
  5337. //
  5338. // Descrip:
  5339. //
  5340. // Returns: DWORD
  5341. //
  5342. // Notes: none
  5343. //
  5344. // History: 09/17/2001 xiaoz created
  5345. //
  5346. // Notes:
  5347. // lpszLongPath is the long path name
  5348. // lpszOriginalPath (optional)is the the original name of lpszLongPath(before we renamed it)
  5349. // lpszShortPath is the buffer to receive the short path name
  5350. // cchBuffer is the buffer size for lpszShortPath
  5351. //
  5352. //-----------------------------------------------------------------------
  5353. #define BYTE_COUNT_8_DOT_3 (24)
  5354. HRESULT MyGetShortPathName(
  5355. IN LPCTSTR lpszPathRoot,
  5356. IN LPCTSTR lpszOldName,
  5357. IN LPCTSTR lpszNewName,
  5358. OUT LPTSTR lpszShortName,
  5359. IN DWORD cchBuffer)
  5360. {
  5361. HRESULT hr = S_OK;
  5362. GENERATE_NAME_CONTEXT NameContext;
  5363. WCHAR ShortNameBuffer[BYTE_COUNT_8_DOT_3 / sizeof( WCHAR ) + 1];
  5364. UNICODE_STRING FileName,ShortName;
  5365. DWORD StringLength;
  5366. LPTSTR lpName;
  5367. TCHAR szPath[MAX_PATH],szLongPath[MAX_PATH];
  5368. TCHAR DriveRoot[_MAX_DRIVE + 2];
  5369. #define FILESYSNAMEBUFSIZE 1024 // probably more than we need
  5370. TCHAR szFileSystemType[FILESYSNAMEBUFSIZE];
  5371. BOOL bIsNTFS = FALSE;
  5372. BOOL bTmpDirCreated = FALSE;
  5373. DWORD dwAllowExtendedChar;
  5374. BOOLEAN bAllowExtendedChar;
  5375. DWORD dwsizeofdw;
  5376. if (lstrlen(lpszNewName) <= 8)
  5377. {
  5378. hr = StringCchCopy(lpszShortName,cchBuffer,lpszNewName);
  5379. goto Exit;
  5380. }
  5381. //
  5382. // Initialize the short string to use the input buffer.
  5383. //
  5384. ShortName.Buffer = ShortNameBuffer;
  5385. ShortName.MaximumLength = BYTE_COUNT_8_DOT_3;
  5386. FileName.Buffer = (LPTSTR)lpszNewName;
  5387. StringLength = lstrlen(lpszNewName);
  5388. FileName.Length = (USHORT)StringLength * sizeof(TCHAR);
  5389. FileName.MaximumLength = (USHORT)(StringLength + 1)*sizeof(TCHAR);
  5390. // Initialize the name context.
  5391. //
  5392. RtlZeroMemory( &NameContext, sizeof( GENERATE_NAME_CONTEXT ));
  5393. #define EXTENDED_CHAR_MODE_VALUE_NAME TEXT("NtfsAllowExtendedCharacterIn8dot3Name")
  5394. #define COMPATIBILITY_MODE_KEY_NAME TEXT("System\\CurrentControlSet\\Control\\FileSystem")
  5395. dwsizeofdw = sizeof(DWORD);
  5396. if (ERROR_SUCCESS == GetRegistryValue(HKEY_LOCAL_MACHINE,
  5397. COMPATIBILITY_MODE_KEY_NAME,
  5398. EXTENDED_CHAR_MODE_VALUE_NAME,
  5399. (LPBYTE)&dwAllowExtendedChar,
  5400. &dwsizeofdw))
  5401. {
  5402. if (dwAllowExtendedChar)
  5403. {
  5404. bAllowExtendedChar = TRUE;
  5405. }
  5406. else
  5407. {
  5408. bAllowExtendedChar = FALSE;
  5409. }
  5410. }
  5411. else
  5412. {
  5413. bAllowExtendedChar = FALSE;
  5414. }
  5415. RtlGenerate8dot3Name( &FileName, bAllowExtendedChar, &NameContext, &ShortName );
  5416. //now ShortName.Buffer contains the shortpath and is NULL ended
  5417. ShortName.Buffer[ShortName.Length /sizeof(TCHAR)] = TEXT('\0');
  5418. //check whether the short name is exitsted or now
  5419. hr = StringCchCopy(szPath,ARRAYSIZE(szPath),lpszPathRoot);
  5420. if (FAILED(hr))
  5421. {
  5422. goto Exit;
  5423. }
  5424. if (!ConcatenatePaths(szPath,ShortName.Buffer,ARRAYSIZE(szPath)))
  5425. {
  5426. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  5427. goto Exit;
  5428. }
  5429. if (!IsFileFolderExisting(szPath))
  5430. {
  5431. hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer);
  5432. goto Exit;
  5433. }
  5434. _tsplitpath(lpszPathRoot, DriveRoot, NULL, NULL, NULL);
  5435. hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\"));
  5436. if (FAILED(hr))
  5437. {
  5438. hr = E_INVALIDARG;
  5439. goto Exit;
  5440. }
  5441. if (! GetVolumeInformation(DriveRoot, NULL, 0,
  5442. NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) )
  5443. {
  5444. hr = HRESULT_FROM_WIN32(GetLastError());
  5445. goto Exit;
  5446. }
  5447. if (!MyStrCmpI(szFileSystemType,TEXT("NTFS")))
  5448. {
  5449. bIsNTFS = TRUE;
  5450. }
  5451. //Follwing we process the short name path is existing.
  5452. if (!GetLongPathName(szPath,szLongPath,ARRAYSIZE(szLongPath)))
  5453. {
  5454. hr = HRESULT_FROM_WIN32(GetLastError());
  5455. goto Exit;
  5456. }
  5457. lpName = StrRChrI(szLongPath,NULL,TEXT('\\'));
  5458. if (!lpName)
  5459. {
  5460. hr = E_FAIL;
  5461. goto Exit;
  5462. }
  5463. if (!MyStrCmpI(lpName+1,lpszOldName))
  5464. {
  5465. if (bIsNTFS)
  5466. {
  5467. hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer);
  5468. goto Exit;
  5469. }
  5470. }
  5471. else
  5472. if (!MyStrCmpI(lpName,lpszNewName))
  5473. {
  5474. hr = StringCchCopy(lpszShortName,cchBuffer,ShortName.Buffer);
  5475. goto Exit;
  5476. }
  5477. //here we need to get the shortpath name by creating it
  5478. hr = StringCchCopy(szLongPath,ARRAYSIZE(szLongPath),lpszPathRoot);
  5479. if (FAILED(hr))
  5480. {
  5481. goto Exit;
  5482. }
  5483. if (!ConcatenatePaths(szLongPath,lpszNewName,ARRAYSIZE(szLongPath)))
  5484. {
  5485. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  5486. goto Exit;
  5487. }
  5488. if (!CreateDirectory(szLongPath,NULL))
  5489. {
  5490. DWORD dwErr = GetLastError();
  5491. if (dwErr != ERROR_ALREADY_EXISTS)
  5492. {
  5493. hr = HRESULT_FROM_WIN32(dwErr);
  5494. goto Exit;
  5495. }
  5496. }
  5497. else
  5498. {
  5499. bTmpDirCreated = TRUE;
  5500. }
  5501. if (!GetShortPathName(szLongPath,szPath,cchBuffer))
  5502. {
  5503. hr = HRESULT_FROM_WIN32(GetLastError());
  5504. goto Exit;
  5505. }
  5506. if (bTmpDirCreated)
  5507. {
  5508. RemoveDirectory(szLongPath);
  5509. }
  5510. if (!(lpName = StrRChrI(szPath,NULL,TEXT('\\'))))
  5511. {
  5512. hr = E_FAIL;
  5513. goto Exit;
  5514. }
  5515. hr = StringCchCopy(lpszShortName,cchBuffer,lpName+1);
  5516. Exit:
  5517. return hr;
  5518. }
  5519. BOOL
  5520. MassageLinkValue(
  5521. IN LPCWSTR lpLinkName,
  5522. IN LPCWSTR lpLinkValue,
  5523. OUT PUNICODE_STRING NtLinkName,
  5524. OUT PUNICODE_STRING NtLinkValue,
  5525. OUT PUNICODE_STRING DosLinkValue
  5526. )
  5527. {
  5528. PWSTR FilePart;
  5529. PWSTR s, sBegin, sBackupLimit, sLinkName;
  5530. NTSTATUS Status;
  5531. USHORT nSaveNtNameLength;
  5532. ULONG nLevels;
  5533. //
  5534. // Initialize output variables to NULL
  5535. //
  5536. RtlInitUnicodeString( NtLinkName, NULL );
  5537. RtlInitUnicodeString( NtLinkValue, NULL );
  5538. //
  5539. // Translate link name into full NT path.
  5540. //
  5541. if (!RtlDosPathNameToNtPathName_U( lpLinkName,
  5542. NtLinkName,
  5543. &sLinkName,
  5544. NULL
  5545. )
  5546. )
  5547. {
  5548. return FALSE;
  5549. }
  5550. //
  5551. // All done if no link value.
  5552. //
  5553. if (!ARGUMENT_PRESENT( lpLinkValue )) {
  5554. return TRUE;
  5555. }
  5556. //
  5557. // If the target is a device, do not allow the link.
  5558. //
  5559. if (RtlIsDosDeviceName_U( (PWSTR)lpLinkValue )) {
  5560. return FALSE;
  5561. }
  5562. //
  5563. // Convert to DOS path to full path, and get Nt representation
  5564. // of DOS path.
  5565. //
  5566. if (!RtlGetFullPathName_U( lpLinkValue,
  5567. DosLinkValue->MaximumLength,
  5568. DosLinkValue->Buffer,
  5569. NULL
  5570. )
  5571. ) {
  5572. return FALSE;
  5573. }
  5574. DosLinkValue->Length = wcslen( DosLinkValue->Buffer ) * sizeof( WCHAR );
  5575. //
  5576. // Verify that the link value is a valid NT name.
  5577. //
  5578. if (!RtlDosPathNameToNtPathName_U( DosLinkValue->Buffer,
  5579. NtLinkValue,
  5580. NULL,
  5581. NULL
  5582. )
  5583. ) {
  5584. return FALSE;
  5585. }
  5586. return TRUE;
  5587. } // MassageLinkValue
  5588. BOOL CreateSymbolicLink(
  5589. LPTSTR szLinkName,
  5590. LPTSTR szLinkValue,
  5591. BOOL bMakeLinkHidden
  5592. )
  5593. {
  5594. NTSTATUS Status = STATUS_SUCCESS;
  5595. OBJECT_ATTRIBUTES ObjectAttributes;
  5596. HANDLE Handle;
  5597. UNICODE_STRING UnicodeName;
  5598. UNICODE_STRING NtLinkName;
  5599. UNICODE_STRING NtLinkValue;
  5600. UNICODE_STRING DosLinkValue;
  5601. WCHAR FullPathLinkValue[ DOS_MAX_PATH_LENGTH+1 ];
  5602. IO_STATUS_BLOCK IoStatusBlock;
  5603. BOOL TranslationStatus;
  5604. PVOID FreeBuffer;
  5605. PVOID FreeBuffer2;
  5606. FILE_DISPOSITION_INFORMATION Disposition;
  5607. PREPARSE_DATA_BUFFER ReparseBufferHeader = NULL;
  5608. PCHAR ReparseBuffer = NULL;
  5609. ULONG ReparsePointTag = IO_REPARSE_TAG_RESERVED_ZERO;
  5610. USHORT ReparseDataLength = 0;
  5611. ULONG FsControlCode = 0;
  5612. ULONG CreateOptions = 0;
  5613. ULONG CreateDisposition = 0;
  5614. ULONG DesiredAccess = SYNCHRONIZE;
  5615. DWORD dwAttrib;
  5616. BOOL bRet = FALSE;
  5617. // change the name to NT path, eg d:\programme to ??\d:\programme
  5618. TranslationStatus = RtlDosPathNameToNtPathName_U(
  5619. szLinkName,
  5620. &UnicodeName,
  5621. NULL,
  5622. NULL
  5623. );
  5624. if (!TranslationStatus)
  5625. {
  5626. goto exit;
  5627. }
  5628. FreeBuffer = UnicodeName.Buffer;
  5629. InitializeObjectAttributes(
  5630. &ObjectAttributes,
  5631. &UnicodeName,
  5632. OBJ_CASE_INSENSITIVE,
  5633. NULL,
  5634. NULL
  5635. );
  5636. //
  5637. // Set the code of the FSCTL operation.
  5638. //
  5639. FsControlCode = FSCTL_SET_REPARSE_POINT;
  5640. //
  5641. // Set the open/create options for a directory.
  5642. //
  5643. CreateOptions = FILE_OPEN_REPARSE_POINT;
  5644. //
  5645. // Set the tag to mount point.
  5646. //
  5647. ReparsePointTag = IO_REPARSE_TAG_MOUNT_POINT;
  5648. //
  5649. // Open to set the reparse point.
  5650. //
  5651. DesiredAccess |= FILE_WRITE_DATA;
  5652. CreateDisposition = FILE_OPEN; // the file must be present
  5653. Status = NtCreateFile(&Handle,
  5654. DesiredAccess,
  5655. &ObjectAttributes,
  5656. &IoStatusBlock,
  5657. NULL, // pallocationsize (none!)
  5658. FILE_ATTRIBUTE_NORMAL,// attributes to be set if created
  5659. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  5660. CreateDisposition,
  5661. CreateOptions,
  5662. NULL, // EA buffer (none!)
  5663. 0);
  5664. //
  5665. // Create a directory if you do not find it.
  5666. //
  5667. if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
  5668. {
  5669. DesiredAccess = SYNCHRONIZE;
  5670. CreateDisposition = FILE_CREATE;
  5671. CreateOptions = FILE_DIRECTORY_FILE;
  5672. Status = NtCreateFile(&Handle,
  5673. DesiredAccess,
  5674. &ObjectAttributes,
  5675. &IoStatusBlock,
  5676. NULL, // pallocationsize (none!)
  5677. FILE_ATTRIBUTE_NORMAL, // attributes to be set if created
  5678. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  5679. CreateDisposition,
  5680. CreateOptions,
  5681. NULL, // EA buffer (none!)
  5682. 0);
  5683. if (!NT_SUCCESS(Status))
  5684. {
  5685. goto exit;
  5686. }
  5687. //
  5688. // Close the handle and re-open.
  5689. //
  5690. NtClose( Handle );
  5691. CreateOptions = FILE_OPEN_REPARSE_POINT;
  5692. DesiredAccess |= FILE_WRITE_DATA;
  5693. CreateDisposition = FILE_OPEN; // the file must be present
  5694. Status = NtCreateFile(&Handle,
  5695. DesiredAccess,
  5696. &ObjectAttributes,
  5697. &IoStatusBlock,
  5698. NULL, // pallocationsize (none!)
  5699. FILE_ATTRIBUTE_NORMAL, // attributes to be set if created
  5700. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  5701. CreateDisposition,
  5702. CreateOptions,
  5703. NULL, // EA buffer (none!)
  5704. 0);
  5705. }
  5706. RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
  5707. if (!NT_SUCCESS(Status))
  5708. {
  5709. goto exit;
  5710. }
  5711. //
  5712. // Innitialize the DosName buffer.
  5713. //
  5714. DosLinkValue.Buffer = FullPathLinkValue;
  5715. DosLinkValue.MaximumLength = sizeof( FullPathLinkValue );
  5716. DosLinkValue.Length = 0;
  5717. //
  5718. // Massage all the names.
  5719. //
  5720. if (!MassageLinkValue( szLinkName,
  5721. szLinkValue,
  5722. &NtLinkName,
  5723. &NtLinkValue,
  5724. &DosLinkValue ))
  5725. {
  5726. RtlFreeUnicodeString( &NtLinkName );
  5727. RtlFreeUnicodeString( &NtLinkValue );
  5728. goto exit;
  5729. }
  5730. RtlFreeUnicodeString( &NtLinkName );
  5731. //
  5732. // Set the reparse point with mount point or symbolic link tag and determine
  5733. // the appropriate length of the buffer.
  5734. //
  5735. ReparseDataLength = (USHORT)((FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
  5736. REPARSE_DATA_BUFFER_HEADER_SIZE) +
  5737. NtLinkValue.Length + sizeof(UNICODE_NULL) +
  5738. DosLinkValue.Length + sizeof(UNICODE_NULL));
  5739. //
  5740. // Allocate a buffer to set the reparse point.
  5741. //
  5742. ReparseBufferHeader
  5743. = (PREPARSE_DATA_BUFFER)RtlAllocateHeap(RtlProcessHeap(),
  5744. HEAP_ZERO_MEMORY,
  5745. REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
  5746. if (ReparseBufferHeader == NULL)
  5747. {
  5748. NtClose( Handle );
  5749. RtlFreeUnicodeString( &NtLinkValue );
  5750. goto exit;
  5751. }
  5752. //
  5753. // Setting the buffer is common for both tags as their buffers have identical fields.
  5754. //
  5755. ReparseBufferHeader->ReparseDataLength = (USHORT)ReparseDataLength;
  5756. ReparseBufferHeader->Reserved = 0;
  5757. ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
  5758. ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameLength = NtLinkValue.Length;
  5759. ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameOffset = NtLinkValue.Length + sizeof( UNICODE_NULL );
  5760. ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameLength = DosLinkValue.Length;
  5761. RtlCopyMemory(ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer,
  5762. NtLinkValue.Buffer,
  5763. NtLinkValue.Length);
  5764. RtlCopyMemory((PCHAR)(ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer)+
  5765. NtLinkValue.Length + sizeof(UNICODE_NULL),
  5766. DosLinkValue.Buffer,
  5767. DosLinkValue.Length);
  5768. RtlFreeUnicodeString( &NtLinkValue );
  5769. //
  5770. // Set the tag
  5771. //
  5772. ReparseBufferHeader->ReparseTag = ReparsePointTag;
  5773. //
  5774. // Set the reparse point.
  5775. //
  5776. Status = NtFsControlFile(Handle,
  5777. NULL,
  5778. NULL,
  5779. NULL,
  5780. &IoStatusBlock,
  5781. FsControlCode,
  5782. ReparseBufferHeader,
  5783. REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseBufferHeader->ReparseDataLength,
  5784. NULL, // no output buffer
  5785. 0); // output buffer length\
  5786. //
  5787. // Close the file.
  5788. //
  5789. NtClose( Handle );
  5790. if (!NT_SUCCESS(Status))
  5791. {
  5792. goto exit;
  5793. }
  5794. bRet = TRUE;
  5795. if (bMakeLinkHidden)
  5796. {
  5797. dwAttrib = GetFileAttributes(szLinkName);
  5798. if (INVALID_FILE_ATTRIBUTES == dwAttrib)
  5799. {
  5800. goto exit;
  5801. }
  5802. if (!SetFileAttributes(szLinkName,dwAttrib|FILE_ATTRIBUTE_HIDDEN))
  5803. {
  5804. DPF (APPmsg, L"SetFileAttributes! Error: %d \n", GetLastError());
  5805. goto exit;
  5806. }
  5807. }
  5808. exit:
  5809. return bRet;
  5810. }
  5811. BOOL GetSymbolicLink(
  5812. LPTSTR szLinkName,
  5813. LPTSTR szLinkValue,
  5814. DWORD cchSize
  5815. )
  5816. {
  5817. NTSTATUS Status = STATUS_SUCCESS;
  5818. OBJECT_ATTRIBUTES ObjectAttributes;
  5819. HANDLE Handle;
  5820. UNICODE_STRING UnicodeName;
  5821. UNICODE_STRING NtLinkName;
  5822. UNICODE_STRING NtLinkValue;
  5823. UNICODE_STRING DosLinkValue;
  5824. WCHAR FullPathLinkValue[ DOS_MAX_PATH_LENGTH+1 ];
  5825. IO_STATUS_BLOCK IoStatusBlock;
  5826. BOOL TranslationStatus;
  5827. PVOID FreeBuffer;
  5828. PVOID FreeBuffer2;
  5829. FILE_DISPOSITION_INFORMATION Disposition;
  5830. PREPARSE_DATA_BUFFER ReparseBufferHeader = NULL;
  5831. PCHAR ReparseBuffer = NULL;
  5832. ULONG ReparsePointTag = IO_REPARSE_TAG_RESERVED_ZERO;
  5833. USHORT ReparseDataLength = 0;
  5834. ULONG FsControlCode = 0;
  5835. ULONG CreateOptions = 0;
  5836. ULONG CreateDisposition = 0;
  5837. ULONG DesiredAccess = SYNCHRONIZE;
  5838. DWORD dwAttrib;
  5839. BOOL bRet = FALSE;
  5840. // change the name to NT path, eg d:\programme to ??\d:\programme
  5841. TranslationStatus = RtlDosPathNameToNtPathName_U(
  5842. szLinkName,
  5843. &UnicodeName,
  5844. NULL,
  5845. NULL
  5846. );
  5847. if (!TranslationStatus)
  5848. {
  5849. goto exit;
  5850. }
  5851. FreeBuffer = UnicodeName.Buffer;
  5852. InitializeObjectAttributes(
  5853. &ObjectAttributes,
  5854. &UnicodeName,
  5855. OBJ_CASE_INSENSITIVE,
  5856. NULL,
  5857. NULL
  5858. );
  5859. FsControlCode = FSCTL_GET_REPARSE_POINT;
  5860. DesiredAccess = FILE_READ_DATA | SYNCHRONIZE;
  5861. CreateOptions = FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT;
  5862. //
  5863. // Set the tag to mount point.
  5864. //
  5865. ReparsePointTag = IO_REPARSE_TAG_MOUNT_POINT;
  5866. Status = NtOpenFile(
  5867. &Handle,
  5868. DesiredAccess,
  5869. &ObjectAttributes,
  5870. &IoStatusBlock,
  5871. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  5872. CreateOptions
  5873. );
  5874. RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
  5875. if (!NT_SUCCESS(Status))
  5876. {
  5877. goto exit;
  5878. }
  5879. ReparseDataLength = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
  5880. ReparseBuffer = RtlAllocateHeap(
  5881. RtlProcessHeap(),
  5882. HEAP_ZERO_MEMORY,
  5883. ReparseDataLength
  5884. );
  5885. if (ReparseBuffer == NULL)
  5886. {
  5887. goto exit;
  5888. }
  5889. Status = NtFsControlFile(
  5890. Handle,
  5891. NULL,
  5892. NULL,
  5893. NULL,
  5894. &IoStatusBlock,
  5895. FsControlCode, // no input buffer
  5896. NULL, // input buffer length
  5897. 0,
  5898. (PVOID)ReparseBuffer,
  5899. ReparseDataLength
  5900. );
  5901. if (!NT_SUCCESS(Status))
  5902. {
  5903. NtClose( Handle );
  5904. RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader );
  5905. goto exit;
  5906. }
  5907. NtClose( Handle );
  5908. ReparseBufferHeader = (PREPARSE_DATA_BUFFER)ReparseBuffer;
  5909. if ((ReparseBufferHeader->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) ||
  5910. (ReparseBufferHeader->ReparseTag == IO_REPARSE_TAG_SYMBOLIC_LINK))
  5911. {
  5912. USHORT Offset = 0;
  5913. NtLinkValue.Buffer = &ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer[Offset];
  5914. NtLinkValue.Length = ReparseBufferHeader->SymbolicLinkReparseBuffer.SubstituteNameLength;
  5915. Offset = NtLinkValue.Length + sizeof(UNICODE_NULL);
  5916. DosLinkValue.Buffer = &ReparseBufferHeader->SymbolicLinkReparseBuffer.PathBuffer[Offset/sizeof(WCHAR)];
  5917. DosLinkValue.Length = ReparseBufferHeader->SymbolicLinkReparseBuffer.PrintNameLength;
  5918. if (cchSize < DosLinkValue.Length / sizeof(TCHAR) +1)
  5919. {
  5920. RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader );
  5921. goto exit;
  5922. }
  5923. else
  5924. {
  5925. int cbLen = DosLinkValue.Length;
  5926. LPTSTR lpStart = DosLinkValue.Buffer;
  5927. if (DosLinkValue.Length > 4 * sizeof(TCHAR))
  5928. {
  5929. if ( (DosLinkValue.Buffer[0] == TEXT('\\'))
  5930. && (DosLinkValue.Buffer[1] == TEXT('\\'))
  5931. && (DosLinkValue.Buffer[2] == TEXT('?'))
  5932. && (DosLinkValue.Buffer[3] == TEXT('\\')) )
  5933. {
  5934. cbLen -= 4 * sizeof(TCHAR);
  5935. lpStart += 4;
  5936. }
  5937. }
  5938. //memmove((PBYTE)szLinkValue,(PBYTE)DosLinkValue.Buffer,DosLinkValue.Length);
  5939. //szLinkValue[DosLinkValue.Length / sizeof(TCHAR)] = TEXT('\0');
  5940. memmove((PBYTE)szLinkValue,(PBYTE)lpStart,cbLen);
  5941. szLinkValue[cbLen / sizeof(TCHAR)] = TEXT('\0');
  5942. }
  5943. }
  5944. else
  5945. {
  5946. RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader );
  5947. goto exit;
  5948. }
  5949. bRet = TRUE;
  5950. RtlFreeHeap( RtlProcessHeap(), 0, ReparseBufferHeader );
  5951. exit:
  5952. return bRet;
  5953. }
  5954. typedef struct {
  5955. WORD wSuiteMask;
  5956. LPTSTR szSuiteName;
  5957. } SUITE_INFO;
  5958. HRESULT LogMachineInfo()
  5959. {
  5960. SYSTEMTIME systime;
  5961. OSVERSIONINFOEX ov;
  5962. TCHAR lpTimeStr[MAX_PATH];
  5963. TCHAR lpComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  5964. SUITE_INFO c_rgSuite_Info[] = {
  5965. {VER_SUITE_BACKOFFICE, TEXT("Microsoft BackOffice")},
  5966. {VER_SUITE_BLADE, TEXT("Windows Server 2003, Web Edition")},
  5967. {VER_SUITE_DATACENTER, TEXT("Datacenter Server")},
  5968. {VER_SUITE_ENTERPRISE, TEXT("Advanced/Enterprise Server")},
  5969. {VER_SUITE_PERSONAL, TEXT("Windows XP Home Edition")},
  5970. {VER_SUITE_SMALLBUSINESS, TEXT("Small Business Server")},
  5971. {VER_SUITE_SMALLBUSINESS_RESTRICTED, TEXT("Restricted Small Business Server")},
  5972. {VER_SUITE_TERMINAL, TEXT("Terminal Services")},
  5973. {0,NULL}
  5974. };
  5975. SUITE_INFO *psi;
  5976. LCID lcidSys,lcidUser,lcidInstall;
  5977. TCHAR szLocalename[MAX_PATH];
  5978. TCHAR szSystemDir[MAX_PATH+1];
  5979. #define FILESYSNAMEBUFSIZE 1024 // probably more than we need
  5980. TCHAR szFileSystemType[FILESYSNAMEBUFSIZE];
  5981. DWORD cchSize;
  5982. TCHAR szModule[MAX_PATH+1];
  5983. TCHAR szCurrRoot[MAX_PATH+1],szExpRoot[MAX_PATH+1];
  5984. DWORD cchCurrRoot,cchExpRoot;
  5985. HRESULT hr = S_OK;
  5986. if (GetModuleFileName(GetModuleHandle(NULL),szModule,ARRAYSIZE(szModule)-1))
  5987. {
  5988. szModule[ARRAYSIZE(szModule)-1] = TEXT('\0');
  5989. DPF(APPmsg, TEXT("CLMT Version: %s started from %s"),TEXT(VER_FILEVERSION_STR),szModule);
  5990. }
  5991. else
  5992. {
  5993. DPF(APPmsg, TEXT("CLMT Version: %s"),TEXT(VER_FILEVERSION_STR));
  5994. }
  5995. GetSystemTime(&systime);
  5996. if (GetTimeFormat(LOCALE_USER_DEFAULT,0,&systime,NULL,lpTimeStr,ARRAYSIZE(lpTimeStr)))
  5997. {
  5998. DPF(APPmsg, TEXT("CLMT started at %s,%d/%d/%d"),lpTimeStr,systime.wMonth,systime.wDay ,systime.wYear );
  5999. }
  6000. cchSize = ARRAYSIZE(lpComputerName);
  6001. if (GetComputerName(lpComputerName,&cchSize))
  6002. {
  6003. DPF(APPmsg, TEXT("Computer name : %s"),lpComputerName);
  6004. }
  6005. ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  6006. if (GetVersionEx((LPOSVERSIONINFO)&ov))
  6007. {
  6008. TCHAR szProductType[MAX_PATH];
  6009. TCHAR szSuiteList[MAX_PATH];
  6010. DPF(APPmsg, TEXT("OS Version: %d.%d"),ov.dwMajorVersion,ov.dwMinorVersion);
  6011. if (ov.szCSDVersion[0])
  6012. {
  6013. DPF(APPmsg, TEXT("Service Pack: %s"),ov.szCSDVersion);
  6014. }
  6015. switch (ov.wProductType )
  6016. {
  6017. case VER_NT_WORKSTATION:
  6018. hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("NT_WORKSTATION"));
  6019. break;
  6020. case VER_NT_DOMAIN_CONTROLLER:
  6021. hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("DOMAIN_CONTROLLER"));
  6022. break;
  6023. case VER_NT_SERVER :
  6024. hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("NT_SERVER"));
  6025. break;
  6026. default:
  6027. hr = StringCchCopy(szProductType,ARRAYSIZE(szProductType),TEXT("Unknow Type"));
  6028. }
  6029. if (FAILED(hr))
  6030. {
  6031. return hr;
  6032. }
  6033. DPF(APPmsg, TEXT("Product Type: %s"),szProductType);
  6034. szSuiteList[0] = TEXT('\0');
  6035. for (psi = c_rgSuite_Info; psi->szSuiteName; psi++)
  6036. {
  6037. if (psi->wSuiteMask & ov.wSuiteMask)
  6038. {
  6039. hr = StringCchCat(szSuiteList,ARRAYSIZE(szSuiteList),psi->szSuiteName);
  6040. if (FAILED(hr))
  6041. {
  6042. break;
  6043. }
  6044. }
  6045. }
  6046. if (FAILED(hr))
  6047. {
  6048. return hr;
  6049. }
  6050. if (szSuiteList[0])
  6051. {
  6052. DPF(APPmsg, TEXT("Suite List: %s"),szSuiteList);
  6053. }
  6054. }
  6055. lcidSys = GetSystemDefaultLCID();
  6056. lcidUser = GetUserDefaultLCID();
  6057. lcidInstall = GetInstallLocale();
  6058. if (GetLocaleInfo(lcidInstall,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename)))
  6059. {
  6060. DPF(APPmsg, TEXT("OS LanguageID/Name: %x,%s"),lcidInstall,szLocalename);
  6061. }
  6062. else
  6063. {
  6064. DPF(APPmsg, TEXT("OS LanguageID/Name: %x"),lcidInstall);
  6065. }
  6066. if (GetLocaleInfo(lcidSys,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename)))
  6067. {
  6068. DPF(APPmsg, TEXT("System locale ID/Name: %x,%s"),lcidSys,szLocalename);
  6069. }
  6070. else
  6071. {
  6072. DPF(APPmsg, TEXT("System locale ID: %x"),lcidSys);
  6073. }
  6074. if (GetLocaleInfo(lcidUser,LOCALE_SENGLANGUAGE,szLocalename,ARRAYSIZE(szLocalename)))
  6075. {
  6076. DPF(APPmsg, TEXT("User Locale ID/Name: %x,%s"),lcidUser,szLocalename);
  6077. }
  6078. else
  6079. {
  6080. DPF(APPmsg, TEXT("User Locale ID: %x"),lcidUser);
  6081. }
  6082. if (GetSystemDirectory(szSystemDir, ARRAYSIZE(szSystemDir)))
  6083. {
  6084. TCHAR DriveRoot[_MAX_DRIVE + 2];
  6085. ULARGE_INTEGER FreeBytesAvailable; // bytes available to caller
  6086. ULARGE_INTEGER TotalNumberOfBytes; // bytes on disk
  6087. ULARGE_INTEGER TotalNumberOfFreeBytes;
  6088. DPF(APPmsg, TEXT("System Dir is : %s"),szSystemDir);
  6089. _tsplitpath(szSystemDir, DriveRoot, NULL, NULL, NULL);
  6090. if (FAILED(hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\"))))
  6091. {
  6092. return hr;
  6093. }
  6094. if ( GetVolumeInformation(DriveRoot, NULL, 0,
  6095. NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) )
  6096. {
  6097. DPF(APPmsg, TEXT("System Drive File System is : %s"),szFileSystemType);
  6098. }
  6099. if (GetDiskFreeSpaceEx(szSystemDir,&FreeBytesAvailable,&TotalNumberOfBytes,&TotalNumberOfFreeBytes))
  6100. {
  6101. TCHAR szFreeBytesAvailable[64],szTotalNumberOfBytes[64],szTotalNumberOfFreeBytes[64];
  6102. _ui64tot(FreeBytesAvailable.QuadPart,szFreeBytesAvailable,10);
  6103. _ui64tot(TotalNumberOfBytes.QuadPart,szTotalNumberOfBytes,10);
  6104. _ui64tot(TotalNumberOfFreeBytes.QuadPart,szTotalNumberOfFreeBytes,10);
  6105. DPF(APPmsg, TEXT("Free Space Available for system drive : %s"),szFreeBytesAvailable);
  6106. DPF(APPmsg, TEXT("Total Space Available for system drive : %s"),szTotalNumberOfBytes);
  6107. DPF(APPmsg, TEXT("Total Free Space Available for system drive : %s"),szTotalNumberOfFreeBytes);
  6108. }
  6109. }
  6110. cchCurrRoot = ARRAYSIZE(szCurrRoot);
  6111. cchExpRoot = ARRAYSIZE(szExpRoot);
  6112. if ( (GetRegistryValue(HKEY_LOCAL_MACHINE,TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"),
  6113. TEXT("PathName"),(LPBYTE)szExpRoot,&cchExpRoot)==ERROR_SUCCESS)
  6114. && (GetRegistryValue(HKEY_LOCAL_MACHINE,TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"),
  6115. TEXT("SystemRoot"),(LPBYTE)szCurrRoot,&cchCurrRoot)==ERROR_SUCCESS) )
  6116. {
  6117. szExpRoot[1] = TEXT('\0');
  6118. szCurrRoot[1] = TEXT('\0');
  6119. if (MyStrCmpI(szExpRoot,szCurrRoot))
  6120. {
  6121. DPF(APPmsg, TEXT("Warning : System Drive is not correct, supposed to be ---%s Drive---, right now is --- %s Drive ---"),szExpRoot,szCurrRoot);
  6122. DPF(APPmsg, TEXT("Warning : This is usually caused by you ghost the image from one partition, and recover to another"));
  6123. }
  6124. }
  6125. return S_OK;
  6126. }
  6127. HRESULT AddExtraQuoteEtc(
  6128. LPTSTR lpszStrIn,
  6129. LPTSTR *lplpszStrOut)
  6130. {
  6131. LPTSTR lpStart,lpAtSpecialChar,lpDest;
  6132. DWORD cchSpechialCharCount = 0,cchStrLen;
  6133. HRESULT hr;
  6134. LPTSTR szSpecialStrList[] = {TEXT("\""),TEXT("%%"),NULL};
  6135. int i , nCurrSpecialStr;
  6136. TCHAR szTemplate[MAX_PATH];
  6137. if (!lpszStrIn || !lplpszStrOut)
  6138. {
  6139. return E_INVALIDARG;
  6140. }
  6141. i = 0;
  6142. while (szSpecialStrList[i])
  6143. {
  6144. lpStart = lpszStrIn;
  6145. while (lpAtSpecialChar = StrStrI(lpStart,szSpecialStrList[i]))
  6146. {
  6147. cchSpechialCharCount += lstrlen(szSpecialStrList[i]);
  6148. lpStart = lpAtSpecialChar + lstrlen(szSpecialStrList[i]);
  6149. }
  6150. i++;
  6151. }
  6152. if (!cchSpechialCharCount)
  6153. {
  6154. *lplpszStrOut = malloc ( (lstrlen(lpszStrIn) +1) * sizeof(TCHAR));
  6155. if (!*lplpszStrOut)
  6156. {
  6157. return E_OUTOFMEMORY;
  6158. }
  6159. hr = StringCchCopy(*lplpszStrOut,lstrlen(lpszStrIn) +1,lpszStrIn);
  6160. return S_FALSE;
  6161. }
  6162. cchStrLen = lstrlen(lpszStrIn) + cchSpechialCharCount + 1;
  6163. *lplpszStrOut = malloc (cchStrLen * sizeof(TCHAR));
  6164. if (!*lplpszStrOut)
  6165. {
  6166. return E_OUTOFMEMORY;
  6167. }
  6168. hr = StringCchCopy(*lplpszStrOut,cchStrLen,TEXT(""));
  6169. lpStart = lpszStrIn;
  6170. lpAtSpecialChar = lpszStrIn;
  6171. while (*lpStart)
  6172. {
  6173. LPTSTR lp1stSpecialChar = NULL;
  6174. nCurrSpecialStr = 0;
  6175. for (i = 0; szSpecialStrList[i]; i++)
  6176. {
  6177. lpAtSpecialChar = StrStrI(lpStart,szSpecialStrList[i]);
  6178. if (lpAtSpecialChar && !lp1stSpecialChar)
  6179. {
  6180. lp1stSpecialChar = lpAtSpecialChar;
  6181. nCurrSpecialStr = i;
  6182. }
  6183. else if (lpAtSpecialChar && lp1stSpecialChar)
  6184. {
  6185. if (lpAtSpecialChar < lp1stSpecialChar)
  6186. {
  6187. lp1stSpecialChar = lpAtSpecialChar;
  6188. nCurrSpecialStr = i;
  6189. }
  6190. }
  6191. }
  6192. if (lp1stSpecialChar)
  6193. {
  6194. TCHAR chTmp = *lp1stSpecialChar;
  6195. *lp1stSpecialChar = TEXT('\0');
  6196. hr = StringCchCat(*lplpszStrOut,cchStrLen,lpStart);
  6197. *lp1stSpecialChar = chTmp;
  6198. for (i = 0; i< lstrlen(szSpecialStrList[nCurrSpecialStr])* 2; i++)
  6199. {
  6200. szTemplate[i] = chTmp;
  6201. }
  6202. szTemplate[i] = TEXT('\0');
  6203. hr = StringCchCat(*lplpszStrOut,cchStrLen,szTemplate);
  6204. lpStart = lp1stSpecialChar + lstrlen(szSpecialStrList[nCurrSpecialStr]);
  6205. }
  6206. else
  6207. {
  6208. hr = StringCchCat(*lplpszStrOut,cchStrLen,lpStart);
  6209. lpStart = lpStart + lstrlen(lpStart);
  6210. }
  6211. }
  6212. return S_OK;
  6213. }
  6214. HRESULT CopyMyselfTo(LPTSTR lpszDestDir)
  6215. {
  6216. TCHAR szModule[2*MAX_PATH+1];
  6217. LPTSTR lpszNewFile,lpFileName;
  6218. DWORD cchLen;
  6219. BOOL bCopied;
  6220. HRESULT hr;
  6221. if (!lpszDestDir || !lpszDestDir[0])
  6222. {
  6223. return E_INVALIDARG;
  6224. }
  6225. if (!GetModuleFileName(GetModuleHandle(NULL),szModule,ARRAYSIZE(szModule)-1))
  6226. {
  6227. szModule[ARRAYSIZE(szModule)-1] = TEXT('\0');
  6228. return HRESULT_FROM_WIN32(GetLastError());
  6229. }
  6230. lpFileName = StrRChrIW(szModule,NULL,TEXT('\\'));
  6231. if (!lpFileName)
  6232. {
  6233. return E_FAIL;
  6234. }
  6235. lpFileName++;
  6236. if (! *lpFileName)
  6237. {
  6238. return E_FAIL;
  6239. }
  6240. cchLen = lstrlen(lpszDestDir)+ lstrlen(lpFileName) + 2; // one for "\\", one for ending NULL
  6241. if (!(lpszNewFile = malloc(cchLen * sizeof(TCHAR))))
  6242. {
  6243. return E_OUTOFMEMORY;
  6244. }
  6245. //We calculte the buffer for lpszNewFile, so here StringCchCopy should be
  6246. //always success, assinging return value just make prefast happy
  6247. hr = StringCchCopy(lpszNewFile,cchLen,lpszDestDir);
  6248. ConcatenatePaths(lpszNewFile,lpFileName,cchLen);
  6249. bCopied = CopyFile(szModule,lpszNewFile,FALSE);
  6250. if (bCopied)
  6251. {
  6252. free(lpszNewFile);
  6253. return S_OK;
  6254. }
  6255. else
  6256. {
  6257. DWORD dw = GetLastError();
  6258. DWORD dwAttrib = GetFileAttributes(lpszNewFile);
  6259. if ( (dwAttrib & FILE_ATTRIBUTE_READONLY)
  6260. ||(dwAttrib & FILE_ATTRIBUTE_SYSTEM) )
  6261. {
  6262. if (SetFileAttributes(lpszNewFile,FILE_ATTRIBUTE_NORMAL))
  6263. {
  6264. bCopied = CopyFile(szModule,lpszNewFile,FALSE);
  6265. if (bCopied)
  6266. {
  6267. dw = ERROR_SUCCESS;
  6268. }
  6269. else
  6270. {
  6271. dw = GetLastError();
  6272. }
  6273. }
  6274. }
  6275. free(lpszNewFile);
  6276. return HRESULT_FROM_WIN32(dw);
  6277. }
  6278. }
  6279. // local functions
  6280. HRESULT SetRunOnceValue (
  6281. IN LPCTSTR szValueName,
  6282. IN LPCTSTR szValue)
  6283. {
  6284. HKEY hRunOnceKey = NULL;
  6285. DWORD dwStatus = ERROR_SUCCESS;
  6286. DWORD cbData;
  6287. const TCHAR* szRunOnceKeyPath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce");
  6288. if (NULL == szValueName || TEXT('\0') == szValueName[0])
  6289. {
  6290. dwStatus = ERROR_INVALID_PARAMETER;
  6291. goto SetRunOnceValueEnd;
  6292. }
  6293. if (NULL == szValue || TEXT('\0') == szValue[0])
  6294. {
  6295. dwStatus = ERROR_INVALID_PARAMETER;
  6296. goto SetRunOnceValueEnd;
  6297. }
  6298. dwStatus = RegOpenKey (HKEY_LOCAL_MACHINE, szRunOnceKeyPath, &hRunOnceKey);
  6299. if (ERROR_SUCCESS != dwStatus)
  6300. {
  6301. goto SetRunOnceValueEnd;
  6302. }
  6303. cbData = ( lstrlen(szValue) + 1) * sizeof(TCHAR);
  6304. dwStatus = RegSetValueEx (hRunOnceKey,
  6305. szValueName,
  6306. 0, // Reserved
  6307. REG_SZ,
  6308. (CONST BYTE *) szValue,
  6309. cbData);
  6310. SetRunOnceValueEnd:
  6311. if (hRunOnceKey)
  6312. {
  6313. RegCloseKey(hRunOnceKey);
  6314. }
  6315. return HRESULT_FROM_WIN32(dwStatus);
  6316. }
  6317. //-----------------------------------------------------------------------
  6318. //
  6319. // Function: SetRunValue
  6320. //
  6321. // Descrip:
  6322. //
  6323. // Returns: BOOL
  6324. //
  6325. // Notes: none
  6326. //
  6327. // History:
  6328. //
  6329. // Notes:
  6330. //
  6331. //-----------------------------------------------------------------------
  6332. HRESULT SetRunValue(
  6333. LPCTSTR szValueName,
  6334. LPCTSTR szValue
  6335. )
  6336. {
  6337. HKEY hRunKey = NULL;
  6338. DWORD dwStatus = ERROR_SUCCESS;
  6339. DWORD cbData;
  6340. if (NULL == szValueName || TEXT('\0') == szValueName[0] ||
  6341. NULL == szValue || TEXT('\0') == szValue[0])
  6342. {
  6343. return E_INVALIDARG;
  6344. }
  6345. dwStatus = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT_RUN_KEY, &hRunKey);
  6346. if (ERROR_SUCCESS == dwStatus)
  6347. {
  6348. cbData = (lstrlen(szValue) + 1) * sizeof(TCHAR);
  6349. dwStatus = RegSetValueEx(hRunKey,
  6350. szValueName,
  6351. 0,
  6352. REG_SZ,
  6353. (CONST BYTE *) szValue,
  6354. cbData);
  6355. RegCloseKey(hRunKey);
  6356. }
  6357. return (HRESULT_FROM_WIN32(dwStatus));
  6358. }
  6359. /*************************************************************
  6360. *
  6361. * CreateSd(void)
  6362. * Creates a SECURITY_DESCRIPTOR for administrators group.
  6363. *
  6364. * NOTES:
  6365. * Caller must free the returned buffer if not NULL.
  6366. *
  6367. * RETURN CODES:
  6368. *
  6369. *************************************************************/
  6370. HRESULT CreateAdminsSd( PSECURITY_DESCRIPTOR *ppSD)
  6371. {
  6372. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  6373. PSID BuiltInAdministrators = NULL;
  6374. PSECURITY_DESCRIPTOR Sd = NULL;
  6375. ULONG AclSize;
  6376. ACL *Acl;
  6377. HRESULT hr;
  6378. if( ! AllocateAndInitializeSid(
  6379. &sia,
  6380. 2,
  6381. SECURITY_BUILTIN_DOMAIN_RID,
  6382. DOMAIN_ALIAS_RID_ADMINS,
  6383. 0, 0, 0, 0, 0, 0,
  6384. &BuiltInAdministrators
  6385. ))
  6386. {
  6387. hr = HRESULT_FROM_WIN32(GetLastError());
  6388. goto Exit;
  6389. }
  6390. //
  6391. // Calculate the size of and allocate a buffer for the DACL, we need
  6392. // this value independently of the total alloc size for ACL init.
  6393. //
  6394. //
  6395. // "- sizeof (ULONG)" represents the SidStart field of the
  6396. // ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
  6397. // SID, this field is counted twice.
  6398. // See detail in InitializeAcl in MSDN
  6399. AclSize = sizeof (ACL) +
  6400. (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG)) +
  6401. GetLengthSid(BuiltInAdministrators) ;
  6402. Sd = LocalAlloc(LMEM_FIXED + LMEM_ZEROINIT,
  6403. SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
  6404. if (!Sd)
  6405. {
  6406. hr = E_OUTOFMEMORY;
  6407. goto Exit;
  6408. }
  6409. Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  6410. if (!InitializeAcl(Acl,
  6411. AclSize,
  6412. ACL_REVISION))
  6413. {
  6414. hr = HRESULT_FROM_WIN32(GetLastError());
  6415. goto Exit;
  6416. }
  6417. //#define ACCESS_ALL GENERIC_ALL | STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL
  6418. if (!AddAccessAllowedAce(Acl,
  6419. ACL_REVISION,
  6420. //GENERIC_READ | GENERIC_WRITE,
  6421. GENERIC_ALL,
  6422. BuiltInAdministrators))
  6423. {
  6424. // Failed to build the ACE granting "Built-in Administrators"
  6425. // STANDARD_RIGHTS_ALL access.
  6426. hr = HRESULT_FROM_WIN32(GetLastError());
  6427. goto Exit;
  6428. }
  6429. if (!InitializeSecurityDescriptor(Sd,SECURITY_DESCRIPTOR_REVISION))
  6430. {
  6431. // error
  6432. hr = HRESULT_FROM_WIN32(GetLastError());
  6433. goto Exit;
  6434. }
  6435. if (!SetSecurityDescriptorDacl(Sd,
  6436. TRUE,
  6437. Acl,
  6438. FALSE))
  6439. {
  6440. hr = HRESULT_FROM_WIN32(GetLastError());
  6441. goto Exit;
  6442. }
  6443. *ppSD = Sd;
  6444. hr = S_OK;
  6445. Exit:
  6446. /* A jump of last resort */
  6447. if (hr != S_OK)
  6448. {
  6449. *ppSD = NULL;
  6450. if (Sd)
  6451. {
  6452. LocalFree(Sd);
  6453. } // error
  6454. }
  6455. if (BuiltInAdministrators)
  6456. {
  6457. FreeSid(BuiltInAdministrators);
  6458. }
  6459. return hr;
  6460. }
  6461. /*************************************************************
  6462. *
  6463. * MyStrCmpIA/W
  6464. * Do locale independent string comparison(case-insensive)
  6465. *
  6466. * NOTES:
  6467. * It's just a wrapper for CompareString with LOCALE_INVARIANT
  6468. * we can not use LOCALE_INVARIANT since this is XP+ only
  6469. *
  6470. * RETURN CODES: see lstrcmpi in MSDN
  6471. *
  6472. *************************************************************/
  6473. int MyStrCmpIW(
  6474. LPCWSTR lpString1,
  6475. LPCWSTR lpString2)
  6476. {
  6477. return ( CompareStringW(LOCALE_ENGLISH, NORM_IGNORECASE,
  6478. lpString1, -1, lpString2, -1) - 2);
  6479. }
  6480. int MyStrCmpIA(
  6481. LPCSTR lpString1,
  6482. LPCSTR lpString2)
  6483. {
  6484. return ( CompareStringA(LOCALE_ENGLISH, NORM_IGNORECASE,
  6485. lpString1, -1, lpString2, -1) - 2);
  6486. }
  6487. //-----------------------------------------------------------------------
  6488. //
  6489. // Function: MergeDirectory
  6490. //
  6491. // Descrip: Merge the contents inside source directory to destination
  6492. // directory. If file/folder in source dir does not exist in
  6493. // destination dir, we will add it to CLMTDO.inf. These files
  6494. // or folders will be moved in DoCriticalWork().
  6495. //
  6496. // Returns: S_OK if function succeeded.
  6497. // S_FALSE if source directory does not exist
  6498. // else if error occured
  6499. //
  6500. // Notes: none
  6501. //
  6502. // History: 04/30/2002 rerkboos created
  6503. //
  6504. // Notes: none
  6505. //
  6506. //-----------------------------------------------------------------------
  6507. HRESULT MergeDirectory(
  6508. LPCTSTR lpSrcDir,
  6509. LPCTSTR lpDstDir
  6510. )
  6511. {
  6512. HRESULT hr = S_OK;
  6513. BOOL bRet;
  6514. WIN32_FIND_DATA FindFileData;
  6515. HANDLE hFile;
  6516. TCHAR szDstFile[MAX_PATH];
  6517. TCHAR szSrcFile[MAX_PATH];
  6518. TCHAR szSearchPath[MAX_PATH];
  6519. if (!IsDirExisting((LPTSTR) lpSrcDir))
  6520. {
  6521. return S_FALSE;
  6522. }
  6523. // Destination directory does not exist, no need to do a merge
  6524. if (!IsDirExisting((LPTSTR) lpDstDir))
  6525. {
  6526. hr = AddFolderRename((LPTSTR)lpSrcDir, (LPTSTR)lpDstDir, TYPE_DIR_MOVE, NULL);
  6527. return hr;
  6528. }
  6529. hr = StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), lpSrcDir);
  6530. if (SUCCEEDED(hr))
  6531. {
  6532. bRet = ConcatenatePaths(szSearchPath, TEXT("*"), ARRAYSIZE(szSearchPath));
  6533. if (!bRet)
  6534. {
  6535. hr = E_UNEXPECTED;
  6536. return hr;
  6537. }
  6538. }
  6539. else
  6540. {
  6541. return hr;
  6542. }
  6543. //
  6544. // Check all files and subdirectores under Source directory
  6545. // Merge contents to destination directory as appropriate
  6546. //
  6547. hFile = FindFirstFileEx(szSearchPath,
  6548. FindExInfoStandard,
  6549. &FindFileData,
  6550. FindExSearchLimitToDirectories,
  6551. NULL,
  6552. 0);
  6553. if (hFile != INVALID_HANDLE_VALUE)
  6554. {
  6555. while (SUCCEEDED(hr))
  6556. {
  6557. // Ignore "." and ".." folders
  6558. if (lstrcmp(FindFileData.cFileName, TEXT(".")) != LSTR_EQUAL
  6559. && lstrcmp(FindFileData.cFileName, TEXT("..")) != LSTR_EQUAL)
  6560. {
  6561. hr = StringCchCopy(szDstFile, ARRAYSIZE(szDstFile), lpDstDir)
  6562. || StringCchCopy(szSrcFile, ARRAYSIZE(szSrcFile), lpSrcDir);
  6563. if (FAILED(hr))
  6564. {
  6565. break;
  6566. }
  6567. bRet = ConcatenatePaths(szDstFile,
  6568. FindFileData.cFileName,
  6569. ARRAYSIZE(szDstFile))
  6570. && ConcatenatePaths(szSrcFile,
  6571. FindFileData.cFileName,
  6572. ARRAYSIZE(szSrcFile));
  6573. if (!bRet)
  6574. {
  6575. hr = E_UNEXPECTED;
  6576. break;
  6577. }
  6578. //
  6579. // Check if the file is a directory or not
  6580. //
  6581. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  6582. {
  6583. // The file is a directory, do a recursive call
  6584. // to merge contents inside it
  6585. hr = MergeDirectory(szSrcFile, szDstFile);
  6586. if (FAILED(hr))
  6587. {
  6588. break;
  6589. }
  6590. }
  6591. else
  6592. {
  6593. // This is just a file, move the file to destination folder
  6594. // if file does not exist in destination folder
  6595. if (!IsFileFolderExisting(szDstFile))
  6596. {
  6597. hr = AddFolderRename(szSrcFile, szDstFile, TYPE_FILE_MOVE, NULL);
  6598. if (FAILED(hr))
  6599. {
  6600. break;
  6601. }
  6602. }
  6603. }
  6604. }
  6605. // Get the next file in source directory
  6606. bRet = FindNextFile(hFile, &FindFileData);
  6607. if (!bRet)
  6608. {
  6609. hr = HRESULT_FROM_WIN32(GetLastError());
  6610. }
  6611. }
  6612. FindClose(hFile);
  6613. if (HRESULT_CODE(hr) == ERROR_NO_MORE_FILES)
  6614. {
  6615. // No more files in source directory, function succeeded
  6616. hr = S_OK;
  6617. }
  6618. }
  6619. else
  6620. {
  6621. hr = HRESULT_FROM_WIN32(GetLastError());
  6622. }
  6623. return hr;
  6624. }
  6625. HRESULT IsNTFS(
  6626. IN LPTSTR lpszPathRoot,
  6627. OUT BOOL *pbIsNTFS)
  6628. {
  6629. TCHAR DriveRoot[_MAX_DRIVE + 2];
  6630. BOOL bIsNTFS = FALSE;
  6631. TCHAR szFileSystemType[FILESYSNAMEBUFSIZE];
  6632. HRESULT hr = S_OK;
  6633. _tsplitpath(lpszPathRoot, DriveRoot, NULL, NULL, NULL);
  6634. if (!pbIsNTFS || !lpszPathRoot || !lpszPathRoot[0])
  6635. {
  6636. hr = E_INVALIDARG;
  6637. goto Exit;
  6638. }
  6639. hr = StringCchCat(DriveRoot, ARRAYSIZE(DriveRoot), TEXT("\\"));
  6640. if (FAILED(hr))
  6641. {
  6642. hr = E_INVALIDARG;
  6643. goto Exit;
  6644. }
  6645. if (! GetVolumeInformation(DriveRoot, NULL, 0,
  6646. NULL, NULL, NULL, szFileSystemType, ARRAYSIZE(szFileSystemType)) )
  6647. {
  6648. hr = HRESULT_FROM_WIN32(GetLastError());
  6649. goto Exit;
  6650. }
  6651. if (!MyStrCmpI(szFileSystemType,TEXT("NTFS")))
  6652. {
  6653. bIsNTFS = TRUE;
  6654. }
  6655. *pbIsNTFS = bIsNTFS;
  6656. Exit:
  6657. return hr;
  6658. }
  6659. HRESULT IsSysVolNTFS(OUT BOOL *pbIsNTFS)
  6660. {
  6661. TCHAR szWindir[MAX_PATH+1];
  6662. if (!GetSystemWindowsDirectory(szWindir, ARRAYSIZE(szWindir)))
  6663. {
  6664. return (HRESULT_FROM_WIN32(GetLastError()));
  6665. }
  6666. return IsNTFS(szWindir,pbIsNTFS);
  6667. }
  6668. BOOL
  6669. CALLBACK
  6670. DoCriticalDlgProc(
  6671. HWND hwndDlg,
  6672. UINT uMsg,
  6673. WPARAM wParam,
  6674. LPARAM lParam
  6675. )
  6676. {
  6677. static HWND hButton1, hButton2, hProgress, hText,hOK, hAdminText;
  6678. static TCHAR szOK[64], szSTART[64],szCANCEL[64],szCRITICALUPDATING[MAX_PATH],
  6679. szREMIND_DO_CRITICAL[1024],szREBOOTING[MAX_PATH],
  6680. szAdminChange[512];
  6681. static DWORD dwTimerProgressDone = 10000, dwTimerTickIncrement = 500 , dwTimerTicks;
  6682. static UINT_PTR dwTimer;
  6683. TCHAR szOldAdminName[MAX_PATH];
  6684. int nRet;
  6685. BOOL bRet;
  6686. HRESULT hr;
  6687. static BOOL bSysUpdated;
  6688. #define ID_TIMER 1
  6689. switch (uMsg)
  6690. {
  6691. case WM_INITDIALOG:
  6692. // Init the dialog
  6693. ShowWindow(hwndDlg, SW_SHOWNORMAL);
  6694. dwTimerTicks = 0;
  6695. bSysUpdated = FALSE;
  6696. LoadString(g_hInstDll,IDS_OK,szOK,ARRAYSIZE(szOK));
  6697. LoadString(g_hInstDll,IDS_START,szSTART,ARRAYSIZE(szSTART));
  6698. LoadString(g_hInstDll,IDS_CANCEL,szCANCEL,ARRAYSIZE(szCANCEL));
  6699. LoadString(g_hInstDll,IDS_REMIND_DO_CRITICAL,szREMIND_DO_CRITICAL,
  6700. ARRAYSIZE(szREMIND_DO_CRITICAL));
  6701. LoadString(g_hInstDll,IDS_CRITICALUPDATING,szCRITICALUPDATING,
  6702. ARRAYSIZE(szCRITICALUPDATING));
  6703. LoadString(g_hInstDll,IDS_REBOOTING,szREBOOTING,ARRAYSIZE(szREBOOTING));
  6704. hButton1 = GetDlgItem(hwndDlg, ID_BUTTON_1);
  6705. hButton2 = GetDlgItem(hwndDlg, ID_BUTTON_2);
  6706. hProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
  6707. hText = GetDlgItem(hwndDlg, IDC_STATIC);
  6708. hOK = GetDlgItem(hwndDlg, IDOK);
  6709. ShowWindow(hProgress,SW_HIDE);
  6710. ShowWindow(hOK,SW_HIDE);
  6711. SetWindowText(hButton1,szSTART);
  6712. SetWindowText(hButton2,szCANCEL);
  6713. SetWindowText(hText,szREMIND_DO_CRITICAL);
  6714. SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, dwTimerProgressDone ));
  6715. SetForegroundWindow(hwndDlg);
  6716. break;
  6717. case WM_COMMAND:
  6718. // Handle command buttons
  6719. switch (wParam)
  6720. {
  6721. case ID_BUTTON_1:
  6722. if (bSysUpdated)
  6723. {
  6724. break;
  6725. }
  6726. bSysUpdated = TRUE;
  6727. SetWindowText(hText,szCRITICALUPDATING);
  6728. ShowWindow(hButton1,SW_HIDE);
  6729. ShowWindow(hButton2,SW_HIDE);
  6730. hr = DoCriticalWork();
  6731. if (SUCCEEDED(hr))
  6732. {
  6733. bSysUpdated = TRUE;
  6734. ShowWindow(hOK,SW_SHOW);
  6735. SetFocus(hOK);
  6736. DefDlgProc(hwndDlg,DM_SETDEFID, IDOK, 0);
  6737. dwTimer = SetTimer(hwndDlg,ID_TIMER,dwTimerTickIncrement,NULL);
  6738. if (dwTimer)
  6739. {
  6740. ShowWindow(hProgress,SW_SHOW);
  6741. SetWindowText(hText,szREBOOTING);
  6742. }
  6743. }
  6744. break;
  6745. case ID_BUTTON_2:
  6746. nRet = DoMessageBox(GetConsoleWindow(), IDS_CONFIRM,
  6747. IDS_MAIN_TITLE, MB_YESNO|MB_SYSTEMMODAL);
  6748. if (IDYES == nRet)
  6749. {
  6750. EndDialog(hwndDlg, ID_BUTTON_2);
  6751. }
  6752. break;
  6753. case IDOK:
  6754. if (bSysUpdated)
  6755. {
  6756. EndDialog(hwndDlg, ID_UPDATE_DONE);
  6757. }
  6758. else
  6759. {
  6760. EndDialog(hwndDlg, IDOK);
  6761. }
  6762. break;
  6763. case ID_UPDATE_DONE:
  6764. EndDialog(hwndDlg, ID_UPDATE_DONE);
  6765. break;
  6766. }
  6767. break;
  6768. case WM_TIMER:
  6769. dwTimerTicks += dwTimerTickIncrement;
  6770. if (dwTimerTicks > dwTimerProgressDone)
  6771. {
  6772. KillTimer(hwndDlg, dwTimer);
  6773. PostMessage(hwndDlg, WM_COMMAND, ID_UPDATE_DONE, 0);
  6774. }
  6775. SendMessage(hProgress, PBM_SETPOS,dwTimerTicks,0);
  6776. break;
  6777. case WM_CLOSE:
  6778. EndDialog(hwndDlg, IDCANCEL);
  6779. break;
  6780. default:
  6781. break;
  6782. }
  6783. return FALSE;
  6784. }
  6785. HRESULT DoCriticalWork ()
  6786. {
  6787. #ifdef CONSOLE_UI
  6788. wprintf(TEXT("updating system settings, !!! Do not Interrupt......\n"));
  6789. #endif
  6790. DPF(APPmsg, TEXT("Enter DoCriticalWork:"));
  6791. BoostMyPriority();
  6792. MakeDOInfCopy();
  6793. g_hInfDoItem = SetupOpenInfFile(g_szToDoINFFileName,
  6794. NULL,
  6795. INF_STYLE_WIN4,
  6796. NULL);
  6797. if (g_hInfDoItem != INVALID_HANDLE_VALUE)
  6798. {
  6799. Remove16bitFEDrivers();
  6800. ResetServicesStatus(g_hInfDoItem, TEXT_SERVICE_STATUS_SECTION);
  6801. ResetServicesStartUp(g_hInfDoItem, TEXT_SERVICE_STARTUP_SECTION);
  6802. // ReconfigureServices(g_hInf);
  6803. BatchUpateIISMetabase(g_hInfDoItem,TEXT("Reg.Update.$MetaBase"));
  6804. BatchFixPathInLink(g_hInfDoItem,TEXT("LNK"));
  6805. BatchINFUpdate(g_hInfDoItem);
  6806. FolderMove(g_hInfDoItem,TEXT("Folder.ObjectRename"),FALSE);
  6807. LoopUser(FinalUpdateRegForUser);
  6808. // The EnumUserProfile() will be enable after RC 1
  6809. // EnumUserProfile(ResetMiscProfilePathPerUser);
  6810. UsrGrpAndDoc_and_SettingsRename(g_hInfDoItem,FALSE);
  6811. UpdateDSObjProp(g_hInfDoItem,DS_OBJ_PROPERTY_UPDATE);
  6812. INFCreateHardLink(g_hInfDoItem,FOLDER_UPDATE_HARDLINK,FALSE);
  6813. SetInstallLocale(0x0409);
  6814. SetProtectedRenamesFlag(TRUE);
  6815. RegUpdate(g_hInfDoItem, NULL , TEXT(""));
  6816. SetupCloseInfFile(g_hInfDoItem);
  6817. DPF(APPmsg, TEXT("Leaving DoCriticalWork:"));
  6818. return S_OK;
  6819. }
  6820. DPF(APPmsg, TEXT("Leaving DoCriticalWork:"));
  6821. return HRESULT_FROM_WIN32( GetLastError() );
  6822. }
  6823. HRESULT RenameRegRoot (
  6824. LPCTSTR lpSrcStr,
  6825. LPTSTR lpDstStr,
  6826. DWORD dwSize,
  6827. LPCTSTR lpUserSid,
  6828. LPCTSTR lpKeyName)
  6829. {
  6830. HRESULT hResult;
  6831. TCHAR szKeyBuf[2*MAX_PATH];
  6832. TCHAR cNonChar = TEXT('\xFFFF');
  6833. if (StrStrI(lpSrcStr, TEXT("HKLM")))
  6834. ReplaceString(lpSrcStr,TEXT("HKLM"),TEXT("MACHINE"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE);
  6835. else if (StrStrI(lpSrcStr, TEXT("HKCR")))
  6836. ReplaceString(lpSrcStr,TEXT("HKCR"),TEXT("CLASSES_ROOT"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE);
  6837. else if (StrStrI(lpSrcStr, TEXT("HKCU")))
  6838. ReplaceString(lpSrcStr,TEXT("HKCU"),TEXT("CURRENT_USER"),szKeyBuf, MAX_PATH*2,&cNonChar, NULL, NULL, TRUE);
  6839. else
  6840. hResult = StringCchPrintf(szKeyBuf, 2*MAX_PATH, TEXT("USERS\\%s%s"), lpUserSid, lpSrcStr);
  6841. if (lpKeyName)
  6842. hResult = StringCchPrintf(lpDstStr, dwSize, TEXT("%s\\%s"), szKeyBuf, lpKeyName);
  6843. else
  6844. hResult = StringCchCopy(lpDstStr, dwSize, szKeyBuf);
  6845. return hResult;
  6846. }
  6847. DWORD AdjustRegSecurity (
  6848. HKEY hRootKey,
  6849. LPCTSTR lpSubKeyName, // Registry sub key path
  6850. LPCTSTR lpszUsersid, // User Sid
  6851. BOOL bSetOrRestore // set or restore the security setting
  6852. )
  6853. {
  6854. DWORD dwRet;
  6855. HRESULT hr;
  6856. TCHAR szKeyName[MAX_PATH*2];
  6857. TCHAR szKeyBuf[MAX_PATH*2];
  6858. if (lpszUsersid && *lpszUsersid)
  6859. {
  6860. if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("\\%s"), lpSubKeyName)))
  6861. goto Exit1;
  6862. }
  6863. else if (hRootKey == HKEY_LOCAL_MACHINE)
  6864. {
  6865. if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("HKLM\\%s"), lpSubKeyName)))
  6866. goto Exit1;
  6867. }
  6868. else if (hRootKey == HKEY_CLASSES_ROOT)
  6869. {
  6870. if (FAILED(hr = StringCchPrintf(szKeyName, MAX_PATH*2-1, TEXT("HKCR\\%s"), lpSubKeyName)))
  6871. goto Exit1;
  6872. }
  6873. RenameRegRoot(szKeyName, szKeyBuf, 2*MAX_PATH-1, lpszUsersid, NULL);
  6874. dwRet = AdjustObjectSecurity(szKeyBuf, SE_REGISTRY_KEY, bSetOrRestore);
  6875. goto Exit;
  6876. Exit1:
  6877. dwRet = HRESULT_CODE(hr);
  6878. Exit:
  6879. return dwRet;
  6880. }
  6881. //-----------------------------------------------------------------------------
  6882. //
  6883. // Function: GetFirstNTFSDrive
  6884. //
  6885. // Descrip: Get the first NTFS drive in the system.
  6886. //
  6887. // Returns: S_OK - Found NTFS partition
  6888. // S_FALSE - NTFS partition not found, return system drive instead
  6889. // Else - Error occured
  6890. //
  6891. // Notes: none
  6892. //
  6893. // History: 04/25/2002 Rerkboos Created
  6894. //
  6895. // Notes: none
  6896. //
  6897. //-----------------------------------------------------------------------------
  6898. HRESULT GetFirstNTFSDrive(
  6899. LPTSTR lpBuffer, // Buffer to store first NTFS drive
  6900. DWORD cchBuffer // Size of buffer in TCHAR
  6901. )
  6902. {
  6903. HRESULT hr = S_OK;
  6904. DWORD dwRet;
  6905. TCHAR szDrives[MAX_PATH];
  6906. LPCTSTR lpDrive;
  6907. BOOL bIsNTFS = FALSE;
  6908. dwRet = GetLogicalDriveStrings(ARRAYSIZE(szDrives), szDrives);
  6909. if (dwRet > 0)
  6910. {
  6911. lpDrive = MultiSzTok(szDrives);
  6912. while (lpDrive != NULL)
  6913. {
  6914. hr = IsNTFS((LPTSTR) lpDrive, &bIsNTFS);
  6915. if (SUCCEEDED(hr))
  6916. {
  6917. if (bIsNTFS)
  6918. {
  6919. lstrcpyn(lpBuffer, lpDrive, 3);
  6920. return S_OK;
  6921. }
  6922. }
  6923. lpDrive = MultiSzTok(NULL);
  6924. }
  6925. }
  6926. // If we reach here, no NTFS partition is found
  6927. // return System drive to caller instead
  6928. hr = S_FALSE;
  6929. if (!GetEnvironmentVariable(TEXT("HOMEDRIVE"), lpBuffer, cchBuffer))
  6930. {
  6931. hr = HRESULT_FROM_WIN32(GetLastError());
  6932. }
  6933. return hr;
  6934. }
  6935. //-----------------------------------------------------------------------------
  6936. //
  6937. // Function: DuplicateString
  6938. //
  6939. // Synopsis: Duplicate the orinal string to a newly allocated buffer.
  6940. //
  6941. // Returns: S_OK if succeeded
  6942. //
  6943. // History: 06/03/2002 rerkboos created
  6944. //
  6945. // Notes: Caller need to free the allocated buffer using MEMFREE() macro
  6946. // or HeapFree() API.
  6947. //
  6948. //-----------------------------------------------------------------------------
  6949. HRESULT DuplicateString(
  6950. LPTSTR *plpDstString, // Pointer to the newly allocated buffer
  6951. LPDWORD lpcchDstString, // Pointer to store size of buffer (in TCHAR)
  6952. LPCTSTR lpOrgString // Original string to duplicate
  6953. )
  6954. {
  6955. HRESULT hr;
  6956. if (plpDstString == NULL || lpcchDstString == NULL)
  6957. {
  6958. return E_INVALIDARG;
  6959. }
  6960. *lpcchDstString = lstrlen(lpOrgString) + 1;
  6961. *plpDstString = MEMALLOC(*lpcchDstString * sizeof(TCHAR));
  6962. if (*plpDstString != NULL)
  6963. {
  6964. hr = StringCchCopy(*plpDstString,
  6965. *lpcchDstString,
  6966. lpOrgString);
  6967. if (FAILED(hr))
  6968. {
  6969. // Free the memory if failed to copy the string
  6970. MEMFREE(*plpDstString);
  6971. }
  6972. }
  6973. else
  6974. {
  6975. *lpcchDstString = 0;
  6976. hr = E_OUTOFMEMORY;
  6977. }
  6978. return hr;
  6979. }
  6980. HRESULT
  6981. SetProtectedRenamesFlag(
  6982. BOOL bSet
  6983. )
  6984. {
  6985. HKEY hKey;
  6986. long rslt = ERROR_SUCCESS;
  6987. HRESULT hr = S_OK;
  6988. rslt = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  6989. TEXT("System\\CurrentControlSet\\Control\\Session Manager"),
  6990. 0,
  6991. KEY_SET_VALUE,
  6992. &hKey);
  6993. if (rslt == ERROR_SUCCESS)
  6994. {
  6995. DWORD Value = bSet ? 1 : 0;
  6996. rslt = RegSetValueEx(hKey,
  6997. TEXT("AllowProtectedRenames"),
  6998. 0,
  6999. REG_DWORD,
  7000. (LPBYTE)&Value,
  7001. sizeof(DWORD));
  7002. RegCloseKey(hKey);
  7003. if (rslt != ERROR_SUCCESS)
  7004. {
  7005. hr = HRESULT_FROM_WIN32(rslt);
  7006. }
  7007. }
  7008. else
  7009. {
  7010. hr = HRESULT_FROM_WIN32(rslt);
  7011. }
  7012. return hr;
  7013. }
  7014. LONG SDBCleanup(
  7015. OUT LPTSTR lpSecDatabase,
  7016. IN DWORD cchLen,
  7017. OUT LPBOOL lpCleanupFailed
  7018. )
  7019. {
  7020. char aszSdbFile[MAX_PATH+1+MAX_PATH];
  7021. TCHAR wszSdbFile[MAX_PATH+1+MAX_PATH];
  7022. TCHAR wszWindir[MAX_PATH+1];
  7023. TCHAR szSdbLogFiles[MAX_PATH+1+MAX_PATH];
  7024. TCHAR szSdbLogFileRoot[MAX_PATH+1+MAX_PATH],szBackupLogFileRoot[MAX_PATH+1+MAX_PATH];
  7025. JET_DBINFOMISC jetdbinfo;
  7026. JET_ERR jetError;
  7027. long lerr = ERROR_SUCCESS;
  7028. HRESULT hr;
  7029. if (!GetSystemWindowsDirectory(wszSdbFile, ARRAYSIZE(wszSdbFile)-MAX_PATH))
  7030. {
  7031. DPF(APPerr, TEXT("Failed to get WINDIR"));
  7032. lerr = GetLastError();
  7033. goto EXIT;
  7034. }
  7035. if (!GetSystemWindowsDirectory(wszWindir, ARRAYSIZE(wszWindir)))
  7036. {
  7037. DPF(APPerr, TEXT("Failed to get WINDIR"));
  7038. lerr = GetLastError();
  7039. goto EXIT;
  7040. }
  7041. hr = StringCchCopy(szSdbLogFiles,ARRAYSIZE(szSdbLogFiles),wszWindir);
  7042. hr = StringCchCopy(szSdbLogFileRoot,ARRAYSIZE(szSdbLogFileRoot),wszWindir);
  7043. hr = StringCchCopy(szBackupLogFileRoot,ARRAYSIZE(szBackupLogFileRoot),wszWindir);
  7044. ConcatenatePaths(szSdbLogFileRoot,TEXT("\\Security"),ARRAYSIZE(szSdbLogFileRoot));
  7045. ConcatenatePaths(szBackupLogFileRoot,TEXT("\\$CLMT_BACKUP$"),ARRAYSIZE(szBackupLogFileRoot));
  7046. ConcatenatePaths(szSdbLogFiles,TEXT("\\Security\\edb?????.log"),ARRAYSIZE(szSdbLogFiles));
  7047. hr = StringCbCat(wszSdbFile, ARRAYSIZE(wszSdbFile), TEXT("\\Security\\Database\\secedit.sdb"));
  7048. if (lpSecDatabase)
  7049. {
  7050. hr = StringCchCopy(lpSecDatabase,cchLen,wszSdbFile);
  7051. }
  7052. WideCharToMultiByte( CP_ACP, 0, wszSdbFile, -1,aszSdbFile,ARRAYSIZE(aszSdbFile),NULL,NULL);
  7053. jetError = JetGetDatabaseFileInfo(aszSdbFile,&jetdbinfo,sizeof(JET_DBINFOMISC),JET_DbInfoMisc);
  7054. if (jetError != JET_errSuccess)
  7055. {
  7056. if (JET_errFileNotFound == jetError)
  7057. {
  7058. lerr = ERROR_SUCCESS;
  7059. }
  7060. else
  7061. {
  7062. lerr = jetError;
  7063. }
  7064. goto EXIT;
  7065. }
  7066. EXIT:
  7067. if (lerr == ERROR_SUCCESS)
  7068. {
  7069. if (jetdbinfo.dbstate == 2)
  7070. {
  7071. if (lpCleanupFailed)
  7072. {
  7073. *lpCleanupFailed = TRUE;
  7074. }
  7075. }
  7076. else
  7077. {
  7078. WIN32_FIND_DATA FindFileData;
  7079. HANDLE hFile = FindFirstFile(szSdbLogFiles,&FindFileData);
  7080. if (hFile != INVALID_HANDLE_VALUE)
  7081. {
  7082. do
  7083. {
  7084. TCHAR szOld[MAX_PATH+1+MAX_PATH],szNew[MAX_PATH+1+MAX_PATH];
  7085. hr = StringCchCopy(szOld,ARRAYSIZE(szOld),szSdbLogFileRoot);
  7086. hr = StringCchCopy(szNew,ARRAYSIZE(szNew),szBackupLogFileRoot);
  7087. ConcatenatePaths(szOld,FindFileData.cFileName ,ARRAYSIZE(szOld));
  7088. ConcatenatePaths(szNew,FindFileData.cFileName ,ARRAYSIZE(szNew));
  7089. AddFolderRename(szOld,szNew,TYPE_FILE_MOVE,NULL);
  7090. }while (FindNextFile(hFile,&FindFileData));
  7091. FindClose(hFile);
  7092. }
  7093. if (lpCleanupFailed)
  7094. {
  7095. *lpCleanupFailed = FALSE;
  7096. }
  7097. }
  7098. }
  7099. return lerr;
  7100. }
  7101. //-----------------------------------------------------------------------
  7102. //
  7103. // Function: DeleteDirectory
  7104. //
  7105. // Descrip: Delete the directory and files inside.
  7106. //
  7107. // Returns: S_OK if function succeeded.
  7108. // S_FALSE if source directory does not exist
  7109. // else if error occured
  7110. //
  7111. // Notes: none
  7112. //
  7113. // History: 07/13/2002 rerkboos created
  7114. //
  7115. // Notes: none
  7116. //
  7117. //-----------------------------------------------------------------------
  7118. HRESULT DeleteDirectory(
  7119. LPCTSTR lpDir
  7120. )
  7121. {
  7122. HRESULT hr = S_OK;
  7123. BOOL bRet;
  7124. WIN32_FIND_DATA FindFileData;
  7125. HANDLE hFile;
  7126. TCHAR szFile[2 * MAX_PATH];
  7127. TCHAR szSearchPath[2 * MAX_PATH];
  7128. if (!IsDirExisting((LPTSTR) lpDir))
  7129. {
  7130. return S_FALSE;
  7131. }
  7132. // Compose the file path inside specified directory
  7133. hr = StringCchCopy(szSearchPath, ARRAYSIZE(szSearchPath), lpDir);
  7134. if (SUCCEEDED(hr))
  7135. {
  7136. bRet = ConcatenatePaths(szSearchPath, TEXT("*"), ARRAYSIZE(szSearchPath));
  7137. if (!bRet)
  7138. {
  7139. hr = E_UNEXPECTED;
  7140. return hr;
  7141. }
  7142. }
  7143. else
  7144. {
  7145. return hr;
  7146. }
  7147. //
  7148. // Delete all files and subdirectores under specified directory
  7149. //
  7150. hFile = FindFirstFileEx(szSearchPath,
  7151. FindExInfoStandard,
  7152. &FindFileData,
  7153. FindExSearchLimitToDirectories,
  7154. NULL,
  7155. 0);
  7156. if (hFile != INVALID_HANDLE_VALUE)
  7157. {
  7158. while (SUCCEEDED(hr))
  7159. {
  7160. // Ignore "." and ".." folders
  7161. if (MyStrCmpI(FindFileData.cFileName, TEXT(".")) != LSTR_EQUAL
  7162. && MyStrCmpI(FindFileData.cFileName, TEXT("..")) != LSTR_EQUAL)
  7163. {
  7164. hr = StringCchCopy(szFile, ARRAYSIZE(szFile), lpDir);
  7165. if (FAILED(hr))
  7166. {
  7167. break;
  7168. }
  7169. bRet = ConcatenatePaths(szFile,
  7170. FindFileData.cFileName,
  7171. ARRAYSIZE(szFile));
  7172. if (!bRet)
  7173. {
  7174. hr = E_UNEXPECTED;
  7175. break;
  7176. }
  7177. //
  7178. // Check if the file is a directory or not
  7179. //
  7180. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  7181. {
  7182. // The file is a directory, do a recursive call
  7183. // to delete contents inside it
  7184. hr = DeleteDirectory(szFile);
  7185. if (FAILED(hr))
  7186. {
  7187. break;
  7188. }
  7189. }
  7190. else
  7191. {
  7192. // This is just a file, delete it
  7193. bRet = DeleteFile(szFile);
  7194. if (!bRet)
  7195. {
  7196. hr = HRESULT_FROM_WIN32(GetLastError());
  7197. break;
  7198. }
  7199. }
  7200. }
  7201. // Get the next file in source directory
  7202. bRet = FindNextFile(hFile, &FindFileData);
  7203. if (!bRet)
  7204. {
  7205. hr = HRESULT_FROM_WIN32(GetLastError());
  7206. }
  7207. }
  7208. FindClose(hFile);
  7209. if (HRESULT_CODE(hr) == ERROR_NO_MORE_FILES)
  7210. {
  7211. // Delete itself
  7212. bRet = RemoveDirectory(lpDir);
  7213. if (bRet)
  7214. {
  7215. // function succeeded
  7216. hr = S_OK;
  7217. }
  7218. else
  7219. {
  7220. hr = HRESULT_FROM_WIN32(GetLastError());
  7221. }
  7222. }
  7223. }
  7224. else
  7225. {
  7226. hr = HRESULT_FROM_WIN32(GetLastError());
  7227. }
  7228. return hr;
  7229. }
  7230. //-----------------------------------------------------------------------
  7231. //
  7232. // Function: MyDeleteFile
  7233. //
  7234. // Descrip: Delete the specified file. The function will set the file
  7235. // attribute to Normal before deletion
  7236. //
  7237. // Returns: S_OK if function succeeded.
  7238. // S_FALSE if source directory does not exist
  7239. // else if error occured
  7240. //
  7241. // Notes: none
  7242. //
  7243. // History: 07/13/2002 rerkboos created
  7244. //
  7245. // Notes: none
  7246. //
  7247. //-----------------------------------------------------------------------
  7248. HRESULT MyDeleteFile(
  7249. LPCTSTR lpFile
  7250. )
  7251. {
  7252. HRESULT hr;
  7253. BOOL bRet;
  7254. bRet = SetFileAttributes(lpFile, FILE_ATTRIBUTE_NORMAL);
  7255. if (bRet)
  7256. {
  7257. bRet = DeleteFile(lpFile);
  7258. }
  7259. hr = (bRet ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  7260. return hr;
  7261. }
  7262. HRESULT GetDCInfo(
  7263. PBOOL pbIsDC,//whether is a DC
  7264. LPTSTR lpszDCName,//if is DC, the DC name
  7265. PDWORD pcchLen)//buffer size for lpszDCName
  7266. {
  7267. PBYTE pdsInfo = NULL;
  7268. DWORD dwErr = ERROR_SUCCESS;
  7269. HRESULT hr = S_OK;
  7270. if (!pbIsDC)
  7271. {
  7272. hr = E_INVALIDARG;
  7273. goto Exit;
  7274. }
  7275. //
  7276. // Check if the machine is Domain Controller or not
  7277. //
  7278. dwErr = DsRoleGetPrimaryDomainInformation(NULL,
  7279. DsRolePrimaryDomainInfoBasic,
  7280. &pdsInfo);
  7281. if (dwErr == ERROR_SUCCESS)
  7282. {
  7283. DSROLE_MACHINE_ROLE dsMachineRole;
  7284. dsMachineRole = ((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->MachineRole;
  7285. if (dsMachineRole == DsRole_RoleBackupDomainController ||
  7286. dsMachineRole == DsRole_RolePrimaryDomainController)
  7287. {
  7288. *pbIsDC = TRUE;
  7289. if (pcchLen)
  7290. {
  7291. if (lpszDCName)
  7292. {
  7293. hr = StringCchCopy(lpszDCName,*pcchLen,
  7294. ((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->DomainNameFlat);
  7295. }
  7296. //
  7297. *pcchLen = lstrlen(((DSROLE_PRIMARY_DOMAIN_INFO_BASIC *) pdsInfo)->DomainNameFlat)+ 1;
  7298. }
  7299. }
  7300. else
  7301. {
  7302. *pbIsDC = FALSE;
  7303. }
  7304. }
  7305. else
  7306. {
  7307. hr = HRESULT_FROM_WIN32(dwErr);
  7308. pdsInfo = NULL;
  7309. goto Exit;
  7310. }
  7311. Exit:
  7312. if (pdsInfo)
  7313. {
  7314. DsRoleFreeMemory(pdsInfo);
  7315. }
  7316. return hr;
  7317. }
  7318. HRESULT GetFQDNForExchange2k(LPTSTR *lplpFQDN)
  7319. {
  7320. LPTSTR lpExchangeFormat = TEXT("LDAP://CN=1,CN=SMTP,CN=Protocols,CN=%s,CN=Servers,CN=%s,CN=Administrative Groups,CN=%s,CN=Microsoft Exchange,CN=Services,CN=Configuration,%s");
  7321. BOOL bIsDC;
  7322. TCHAR szDcName[MAX_PATH+1],szCompname[MAX_PATH+1];
  7323. DWORD cchSize;
  7324. TCHAR szCurrUsrname[MAX_PATH+1];
  7325. LPTSTR lpFQDNCurrUsr = NULL,lpFQDNSuffix,lpFQDNWithldap = NULL;
  7326. DWORD cchPathWithLDAP;
  7327. TCHAR szExchgeReg[2*MAX_PATH];
  7328. LPTSTR lpszAdminGroupName = NULL,lpszOrgName = NULL,lpStart,lpEnd;
  7329. TCHAR cTmp;
  7330. HRESULT hr;
  7331. LONG lstatus;
  7332. cchSize = ARRAYSIZE(szCurrUsrname);
  7333. if (!GetUserName(szCurrUsrname, &cchSize))
  7334. {
  7335. hr = HRESULT_FROM_WIN32(GetLastError());
  7336. goto Exit;
  7337. }
  7338. cchSize = ARRAYSIZE(szDcName);
  7339. hr = GetDCInfo(&bIsDC,szDcName,&cchSize);
  7340. if (FAILED(hr) || !bIsDC)
  7341. {
  7342. if (!bIsDC)
  7343. {
  7344. hr =S_FALSE;
  7345. }
  7346. goto Exit;
  7347. }
  7348. cchSize = ARRAYSIZE(szCompname);
  7349. if (!GetComputerName(szCompname,&cchSize))
  7350. {
  7351. hr = HRESULT_FROM_WIN32(GetLastError());
  7352. goto Exit;
  7353. }
  7354. if (S_OK !=GetFQDN(szCurrUsrname,szDcName,&lpFQDNCurrUsr))
  7355. {
  7356. lpFQDNCurrUsr = NULL;
  7357. goto Exit;
  7358. }
  7359. lpFQDNSuffix = StrStrI(lpFQDNCurrUsr, TEXT("=Users,"));
  7360. if (!lpFQDNSuffix)
  7361. {
  7362. hr = S_FALSE;
  7363. goto Exit;
  7364. }
  7365. lpFQDNSuffix += lstrlen(TEXT("=Users,"));
  7366. cchSize = ARRAYSIZE(szExchgeReg);
  7367. lstatus= RegGetValue(HKEY_LOCAL_MACHINE,
  7368. TEXT("SYSTEM\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"),
  7369. TEXT("SiteDN"), NULL, (LPBYTE)szExchgeReg, &cchSize);
  7370. if (ERROR_SUCCESS != lstatus)
  7371. {
  7372. hr = HRESULT_FROM_WIN32(lstatus);
  7373. goto Exit;
  7374. }
  7375. lpszAdminGroupName = malloc(ARRAYSIZE(szExchgeReg) * sizeof(TCHAR));
  7376. lpszOrgName = malloc(ARRAYSIZE(szExchgeReg) * sizeof(TCHAR));
  7377. if (!lpszAdminGroupName || !lpszOrgName)
  7378. {
  7379. hr = E_OUTOFMEMORY;
  7380. goto Exit;
  7381. }
  7382. //try to get exchnage admin group group name
  7383. //by default it is First Administrative Group
  7384. lpStart = StrStrI(szExchgeReg, TEXT("/ou="));
  7385. if (lpStart)
  7386. {
  7387. lpStart = lpStart + lstrlen(TEXT("/ou="));
  7388. if (!*lpStart)
  7389. {
  7390. hr = S_FALSE;
  7391. goto Exit;
  7392. }
  7393. }
  7394. else
  7395. {
  7396. hr = S_FALSE;
  7397. goto Exit;
  7398. }
  7399. lpEnd = StrStrI(lpStart, TEXT("/"));
  7400. if (lpEnd)
  7401. {
  7402. cTmp = *lpEnd;
  7403. *lpEnd = TEXT('\0');
  7404. }
  7405. hr = StringCchCopy(lpszAdminGroupName,ARRAYSIZE(szExchgeReg),lpStart);
  7406. if (lpEnd)
  7407. {
  7408. *lpEnd = cTmp;
  7409. }
  7410. //try to get ornization name
  7411. lpStart = StrStrI(szExchgeReg, TEXT("/o="));
  7412. if (lpStart)
  7413. {
  7414. lpStart = lpStart + lstrlen(TEXT("/o="));
  7415. if (!*lpStart)
  7416. {
  7417. hr = S_FALSE;
  7418. goto Exit;
  7419. }
  7420. }
  7421. else
  7422. {
  7423. hr = S_FALSE;
  7424. goto Exit;
  7425. }
  7426. lpEnd = StrStrI(lpStart, TEXT("/"));
  7427. if (lpEnd)
  7428. {
  7429. cTmp = *lpEnd;
  7430. *lpEnd = TEXT('\0');
  7431. }
  7432. hr = StringCchCopy(lpszOrgName,ARRAYSIZE(szExchgeReg),lpStart);
  7433. if (lpEnd)
  7434. {
  7435. *lpEnd = cTmp;
  7436. }
  7437. cchPathWithLDAP = lstrlen(lpFQDNSuffix) + lstrlen(szDcName) + lstrlen(szCompname)
  7438. + lstrlen(lpExchangeFormat) + lstrlen(lpszOrgName)
  7439. + lstrlen(lpszAdminGroupName)+ MAX_PATH;
  7440. if (! (lpFQDNWithldap = (LPTSTR) malloc(cchPathWithLDAP * sizeof(TCHAR))))
  7441. {
  7442. hr = E_OUTOFMEMORY;
  7443. goto Exit;
  7444. }
  7445. hr = StringCchPrintf(lpFQDNWithldap,
  7446. cchPathWithLDAP,
  7447. lpExchangeFormat,
  7448. szCompname,
  7449. lpszAdminGroupName,
  7450. lpszOrgName,
  7451. lpFQDNSuffix);
  7452. Exit:
  7453. if (hr == S_OK)
  7454. {
  7455. *lplpFQDN = lpFQDNWithldap;
  7456. }
  7457. else
  7458. {
  7459. FreePointer(lpFQDNWithldap);
  7460. *lplpFQDN = NULL;
  7461. }
  7462. FreePointer(lpFQDNCurrUsr);
  7463. FreePointer(lpszAdminGroupName);
  7464. FreePointer(lpszOrgName);
  7465. return hr;
  7466. }
  7467. HRESULT GetFQDNForFrs(LPTSTR *lplpFQDN)
  7468. {
  7469. BOOL bIsDC;
  7470. TCHAR szDcName[MAX_PATH+1],szCompname[MAX_PATH+1];
  7471. DWORD cchSize;
  7472. TCHAR szCurrUsrname[MAX_PATH+1];
  7473. LPTSTR lpFQDNCurrUsr = NULL,lpFQDNSuffix,lpFQDNWithldap = NULL;
  7474. LPTSTR lpFrsFormat = TEXT("LDAP://CN=Domain System Volume (SYSVOL share),CN=NTFRS Subscriptions,CN=%s,OU=Domain Controllers,%s");
  7475. DWORD cchPathWithLDAP;
  7476. HRESULT hr;
  7477. cchSize = ARRAYSIZE(szCurrUsrname);
  7478. if (!GetUserName(szCurrUsrname, &cchSize))
  7479. {
  7480. hr = HRESULT_FROM_WIN32(GetLastError());
  7481. goto Exit;
  7482. }
  7483. cchSize = ARRAYSIZE(szDcName);
  7484. hr = GetDCInfo(&bIsDC,szDcName,&cchSize);
  7485. if (FAILED(hr) || !bIsDC)
  7486. {
  7487. if (!bIsDC)
  7488. {
  7489. hr =S_FALSE;
  7490. }
  7491. goto Exit;
  7492. }
  7493. cchSize = ARRAYSIZE(szCompname);
  7494. if (!GetComputerName(szCompname,&cchSize))
  7495. {
  7496. hr = HRESULT_FROM_WIN32(GetLastError());
  7497. goto Exit;
  7498. }
  7499. if (S_OK !=GetFQDN(szCurrUsrname,szDcName,&lpFQDNCurrUsr))
  7500. {
  7501. lpFQDNCurrUsr = NULL;
  7502. goto Exit;
  7503. }
  7504. lpFQDNSuffix = StrStrI(lpFQDNCurrUsr, TEXT("=Users,"));
  7505. if (!lpFQDNSuffix)
  7506. {
  7507. hr =S_FALSE;
  7508. goto Exit;
  7509. }
  7510. lpFQDNSuffix += lstrlen(TEXT("=Users,"));
  7511. cchPathWithLDAP = lstrlen(lpFQDNSuffix) + lstrlen(szDcName)
  7512. + lstrlen(lpFrsFormat) + MAX_PATH;
  7513. if (! (lpFQDNWithldap = (LPTSTR) malloc(cchPathWithLDAP * sizeof(TCHAR))))
  7514. {
  7515. hr = E_OUTOFMEMORY;
  7516. goto Exit;
  7517. }
  7518. hr = StringCchPrintf(lpFQDNWithldap,
  7519. cchPathWithLDAP,
  7520. lpFrsFormat,
  7521. szCompname,
  7522. lpFQDNSuffix);
  7523. Exit:
  7524. if (hr == S_OK)
  7525. {
  7526. *lplpFQDN = lpFQDNWithldap;
  7527. }
  7528. else
  7529. {
  7530. FreePointer(lpFQDNWithldap);
  7531. *lplpFQDN = NULL;
  7532. }
  7533. FreePointer(lpFQDNCurrUsr);
  7534. return hr;}
  7535. HRESULT AddDSObjPropUpdate2Inf(
  7536. LPTSTR lpLdpPath,
  7537. LPTSTR lpPropName,
  7538. LPTSTR lpValue)
  7539. {
  7540. LPTSTR lpszOneline = NULL;
  7541. DWORD cchSize ;
  7542. HRESULT hr = S_OK;
  7543. TCHAR szIndex[MAX_PATH];
  7544. if (!lpLdpPath || !lpPropName || !lpValue)
  7545. {
  7546. hr = E_INVALIDARG;
  7547. goto cleanup;
  7548. }
  7549. cchSize = lstrlen(lpLdpPath) + lstrlen(lpPropName) + lstrlen(lpValue) + MAX_PATH;
  7550. if ( ! (lpszOneline = malloc(cchSize * sizeof(TCHAR)) ))
  7551. {
  7552. hr = E_OUTOFMEMORY;
  7553. goto cleanup;
  7554. }
  7555. g_dwKeyIndex++;
  7556. _itot(g_dwKeyIndex,szIndex,16);
  7557. hr = StringCchPrintf(lpszOneline, cchSize, TEXT("\"%s\",\"%s\",\"%s\""),lpLdpPath,lpPropName,lpValue);
  7558. if (!WritePrivateProfileString(DS_OBJ_PROPERTY_UPDATE,szIndex,lpszOneline,g_szToDoINFFileName))
  7559. {
  7560. hr = HRESULT_FROM_WIN32(GetLastError());
  7561. goto cleanup;
  7562. }
  7563. hr = S_OK;
  7564. cleanup:
  7565. FreePointer(lpszOneline);
  7566. return hr;
  7567. }
  7568. HRESULT Ex2000Update()
  7569. {
  7570. LPTSTR lpObjPath = NULL;
  7571. LPTSTR lpBadMailDirectory = NULL, lpPickupDirectory = NULL, lpQueueDirectory = NULL;
  7572. LPTSTR lpNewBadMailDirectory = NULL, lpNewPickupDirectory = NULL, lpNewQueueDirectory = NULL;
  7573. HRESULT hr;
  7574. hr = GetFQDNForExchange2k(&lpObjPath);
  7575. if (hr != S_OK)
  7576. {
  7577. goto exit;
  7578. }
  7579. hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpBadMailDirectory"),&lpBadMailDirectory,NULL);
  7580. if (hr == S_OK)
  7581. {
  7582. if (lpNewBadMailDirectory = ReplaceLocStringInPath(lpBadMailDirectory,TRUE))
  7583. {
  7584. AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpBadMailDirectory"),lpNewBadMailDirectory);
  7585. }
  7586. }
  7587. hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpPickupDirectory"),&lpPickupDirectory,NULL);
  7588. if (hr == S_OK)
  7589. {
  7590. if (lpNewPickupDirectory = ReplaceLocStringInPath(lpPickupDirectory,TRUE))
  7591. {
  7592. AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpPickupDirectory"),lpNewPickupDirectory);
  7593. }
  7594. }
  7595. hr = PropertyValueHelper(lpObjPath,TEXT("msExchSmtpQueueDirectory"),&lpQueueDirectory,NULL);
  7596. if (hr == S_OK)
  7597. {
  7598. if (lpNewQueueDirectory = ReplaceLocStringInPath(lpQueueDirectory,TRUE))
  7599. {
  7600. AddDSObjPropUpdate2Inf(lpObjPath,TEXT("msExchSmtpQueueDirectory"),lpNewQueueDirectory);
  7601. }
  7602. }
  7603. exit:
  7604. FreePointer(lpObjPath);
  7605. FreePointer(lpBadMailDirectory);
  7606. FreePointer(lpPickupDirectory);
  7607. FreePointer(lpQueueDirectory);
  7608. if (lpNewBadMailDirectory)
  7609. {
  7610. MEMFREE(lpNewBadMailDirectory);
  7611. }
  7612. if (lpNewPickupDirectory)
  7613. {
  7614. MEMFREE(lpNewPickupDirectory);
  7615. }
  7616. if (lpNewQueueDirectory)
  7617. {
  7618. MEMFREE(lpNewQueueDirectory);
  7619. }
  7620. return hr;
  7621. }
  7622. HRESULT FRSUpdate()
  7623. {
  7624. LPTSTR lpObjPath = NULL;
  7625. LPTSTR lpfRSRootPath = NULL, lpfRSStagingPath = NULL;
  7626. LPTSTR lpNewfRSRootPath = NULL, lpNewfRSStagingPath = NULL;
  7627. BOOL bChanged = FALSE;
  7628. HRESULT hr;
  7629. TCHAR szSysVolPath[2*MAX_PATH],szSysVolPath2[2*MAX_PATH];
  7630. DWORD cchSize = ARRAYSIZE(szSysVolPath);
  7631. WIN32_FIND_DATA FindFileData;
  7632. HANDLE hFile ;
  7633. hr = GetFQDNForFrs(&lpObjPath);
  7634. if (hr != S_OK)
  7635. {
  7636. goto exit;
  7637. }
  7638. hr = PropertyValueHelper(lpObjPath,TEXT("fRSRootPath"),&lpfRSRootPath,NULL);
  7639. if (hr == S_OK)
  7640. {
  7641. if (lpNewfRSRootPath = ReplaceLocStringInPath(lpfRSRootPath,TRUE))
  7642. {
  7643. AddDSObjPropUpdate2Inf(lpObjPath,TEXT("fRSRootPath"),lpNewfRSRootPath);
  7644. bChanged = TRUE;
  7645. }
  7646. }
  7647. hr = PropertyValueHelper(lpObjPath,TEXT("fRSStagingPath"),&lpfRSStagingPath,NULL);
  7648. if (hr == S_OK)
  7649. {
  7650. if (lpNewfRSStagingPath = ReplaceLocStringInPath(lpfRSStagingPath,TRUE))
  7651. {
  7652. AddDSObjPropUpdate2Inf(lpObjPath,TEXT("fRSStagingPath"),lpNewfRSStagingPath);
  7653. bChanged = TRUE;
  7654. }
  7655. }
  7656. if (bChanged)
  7657. {
  7658. TCHAR szVal[MAX_PATH];
  7659. _itot(210,szVal,10);
  7660. hr = AddRegValueRename(TEXT("HKLM\\SYSTEM\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Backup/Restore\\Process at Startup"),
  7661. TEXT("BurFlags"),
  7662. NULL,
  7663. NULL,
  7664. szVal,
  7665. REG_DWORD,
  7666. 0,
  7667. NULL);
  7668. }
  7669. if (S_OK != GetSharePath(TEXT("SYSVOL"),szSysVolPath,&cchSize))
  7670. {
  7671. goto exit;
  7672. }
  7673. hr = StringCchCopy(szSysVolPath2,ARRAYSIZE(szSysVolPath2),szSysVolPath);
  7674. ConcatenatePaths(szSysVolPath2,TEXT("*.*"),ARRAYSIZE(szSysVolPath2));
  7675. hFile = FindFirstFile(szSysVolPath2,&FindFileData);
  7676. if (hFile != INVALID_HANDLE_VALUE)
  7677. {
  7678. do
  7679. {
  7680. TCHAR szEnrty[MAX_PATH+1+MAX_PATH];
  7681. LPTSTR lpNewLinkPath = NULL, lpNewLinkData = NULL;
  7682. TCHAR szLinkValue[MAX_PATH+1+MAX_PATH];
  7683. if(0 == MyStrCmpI(FindFileData.cFileName , TEXT(".")))
  7684. {
  7685. continue;
  7686. }
  7687. if(0 == MyStrCmpI(FindFileData.cFileName , TEXT("..")))
  7688. {
  7689. continue;
  7690. }
  7691. hr = StringCchCopy(szEnrty,ARRAYSIZE(szEnrty),szSysVolPath);
  7692. ConcatenatePaths(szEnrty,FindFileData.cFileName ,ARRAYSIZE(szEnrty));
  7693. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
  7694. {
  7695. continue;
  7696. }
  7697. if (!GetSymbolicLink(szEnrty,szLinkValue,ARRAYSIZE(szLinkValue)))
  7698. {
  7699. continue;
  7700. }
  7701. if (!(lpNewLinkPath = ReplaceLocStringInPath(szLinkValue,TRUE)))
  7702. {
  7703. continue;
  7704. }
  7705. if (!(lpNewLinkData = ReplaceLocStringInPath(szEnrty,TRUE)))
  7706. {
  7707. lpNewLinkData = szEnrty;
  7708. }
  7709. AddHardLinkEntry(lpNewLinkData,lpNewLinkPath,TEXT("1"),NULL,TEXT("0"),NULL);
  7710. if (lpNewLinkPath && lpNewLinkData != szEnrty)
  7711. {
  7712. MEMFREE(lpNewLinkPath);
  7713. }
  7714. if (lpNewLinkData)
  7715. {
  7716. MEMFREE(lpNewLinkData);
  7717. }
  7718. }while (FindNextFile(hFile,&FindFileData));
  7719. FindClose(hFile);
  7720. }
  7721. exit:
  7722. FreePointer(lpObjPath);
  7723. FreePointer(lpfRSRootPath);
  7724. FreePointer(lpfRSStagingPath);
  7725. if (lpNewfRSRootPath)
  7726. {
  7727. MEMFREE(lpNewfRSRootPath);
  7728. }
  7729. if (lpNewfRSStagingPath)
  7730. {
  7731. MEMFREE(lpNewfRSStagingPath);
  7732. }
  7733. return hr;
  7734. }
  7735. HRESULT GetSharePath(
  7736. LPTSTR lpShareName,
  7737. LPTSTR lpSharePath,
  7738. PDWORD pcchSize)
  7739. {
  7740. HKEY hkey = NULL;
  7741. LONG lstatus;
  7742. HRESULT hr;
  7743. UINT i = 0;
  7744. LPTSTR lpValueName = NULL, lpValueData = NULL;
  7745. DWORD cchValueName, cchValueData, numofentry;
  7746. BOOL bNameMatchFound = FALSE;
  7747. LPTSTR lpPath;
  7748. if (!lpShareName || !pcchSize)
  7749. {
  7750. hr = E_INVALIDARG;
  7751. }
  7752. lstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  7753. TEXT("SYSTEM\\CurrentControlSet\\Services\\lanmanserver\\Shares"),
  7754. 0,
  7755. KEY_READ,
  7756. &hkey);
  7757. if (ERROR_SUCCESS != lstatus)
  7758. {
  7759. hr = HRESULT_FROM_WIN32(lstatus);
  7760. goto exit;
  7761. }
  7762. lstatus = RegQueryInfoKey(hkey,
  7763. NULL,
  7764. NULL,
  7765. 0,
  7766. NULL,
  7767. NULL,
  7768. NULL,
  7769. &numofentry,
  7770. &cchValueName,
  7771. &cchValueData,
  7772. NULL,
  7773. NULL);
  7774. if ( lstatus != ERROR_SUCCESS )
  7775. {
  7776. hr = HRESULT_FROM_WIN32(lstatus);
  7777. goto exit;
  7778. }
  7779. if (!numofentry)
  7780. {
  7781. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  7782. goto exit;
  7783. }
  7784. cchValueName++;
  7785. cchValueData++;
  7786. lpValueName = malloc(cchValueName * sizeof(TCHAR));
  7787. lpValueData = malloc(cchValueData * sizeof(TCHAR));
  7788. if (!lpValueName || !lpValueData)
  7789. {
  7790. hr = E_OUTOFMEMORY;
  7791. goto exit;
  7792. }
  7793. for (i =0; i< numofentry; i++)
  7794. {
  7795. DWORD cchCurrValueName, cchCurrValueData;
  7796. DWORD dwType;
  7797. cchCurrValueName = cchValueName;
  7798. cchCurrValueData = cchValueData;
  7799. lstatus = RegEnumValue(hkey, i, lpValueName, &cchCurrValueName,
  7800. NULL, &dwType, (LPBYTE)lpValueData,&cchCurrValueData);
  7801. if ( (lstatus != ERROR_SUCCESS)
  7802. || (dwType != REG_MULTI_SZ)
  7803. || MyStrCmpI(lpShareName,lpValueName) )
  7804. {
  7805. continue;
  7806. }
  7807. lpPath = lpValueData;
  7808. while (*lpPath)
  7809. {
  7810. if (StrStrI(lpPath, TEXT("Path=")))
  7811. {
  7812. lpPath += lstrlen(TEXT("Path="));
  7813. bNameMatchFound = TRUE;
  7814. break;
  7815. }
  7816. lpPath = lpPath + lstrlen(lpPath) + 1;
  7817. }
  7818. if (bNameMatchFound)
  7819. {
  7820. break;
  7821. }
  7822. }
  7823. if (bNameMatchFound)
  7824. {
  7825. if (*pcchSize < (UINT)lstrlen(lpPath) +1)
  7826. {
  7827. *pcchSize = lstrlen(lpPath) +1;
  7828. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  7829. goto exit;
  7830. }
  7831. *pcchSize = lstrlen(lpPath) +1;
  7832. if (lpSharePath)
  7833. {
  7834. hr = StringCchCopy(lpSharePath,*pcchSize,lpPath);
  7835. }
  7836. else
  7837. {
  7838. hr = S_OK;
  7839. }
  7840. }
  7841. else
  7842. {
  7843. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  7844. goto exit;
  7845. }
  7846. exit:
  7847. FreePointer(lpValueName);
  7848. FreePointer(lpValueData);
  7849. if (hkey)
  7850. {
  7851. RegCloseKey(hkey);
  7852. }
  7853. return hr;
  7854. }
  7855. HRESULT Sz2MultiSZ(
  7856. IN OUT LPTSTR lpsz,
  7857. IN TCHAR chSeperator)
  7858. {
  7859. HRESULT hr;
  7860. LPTSTR lp, lpSep;
  7861. if (!lpsz)
  7862. {
  7863. hr = E_INVALIDARG;
  7864. goto Cleanup;
  7865. }
  7866. lp = lpsz;
  7867. while (*lp && (lpSep = StrChr(lp,chSeperator)))
  7868. {
  7869. *lpSep = TEXT('\0');
  7870. lp = lpSep + 1;
  7871. }
  7872. if (*lp)
  7873. {
  7874. lp = lp + lstrlen(lp) + 1;
  7875. *lp = TEXT('\0');
  7876. }
  7877. hr = S_OK;
  7878. Cleanup:
  7879. return hr;
  7880. }
  7881. HRESULT ConstructUIReplaceStringTable(
  7882. LPTSTR lpszOld,
  7883. LPTSTR lpszNew,
  7884. PREG_STRING_REPLACE pTable)
  7885. {
  7886. DWORD dwNumOld, dwNumNew;
  7887. if (!lpszOld || !lpszNew)
  7888. {
  7889. return E_INVALIDARG;
  7890. }
  7891. dwNumOld = MultiSZNumOfString(lpszOld);
  7892. dwNumNew = MultiSZNumOfString(lpszNew);
  7893. if (!dwNumOld || !dwNumNew || (dwNumOld != dwNumNew))
  7894. {
  7895. return E_INVALIDARG;
  7896. }
  7897. pTable->nNumOfElem = dwNumNew;
  7898. pTable->cchUserName = 0;
  7899. pTable->szUserNameLst = NULL;
  7900. pTable->cchSearchString = MultiSzLen(lpszOld);
  7901. pTable->lpSearchString = lpszOld;
  7902. pTable->cchReplaceString = MultiSzLen(lpszNew);
  7903. pTable->lpReplaceString = lpszNew;
  7904. pTable->cchAttribList = 0;
  7905. pTable->lpAttrib = NULL;
  7906. pTable->cchFullStringList = 0;
  7907. pTable->lpFullStringList = NULL;
  7908. pTable->cchMaxStrLen = 0;
  7909. return S_OK;
  7910. }
  7911. HRESULT MakeDOInfCopy()
  7912. {
  7913. TCHAR szBackupDir[MAX_PATH];
  7914. HRESULT hr;
  7915. TCHAR szDoInf[2*MAX_PATH],szDoInfBackup[2*MAX_PATH];
  7916. if (!GetSystemWindowsDirectory(szBackupDir, ARRAYSIZE(szBackupDir)))
  7917. {
  7918. //BUGBUG:Xiaoz:Add DLG pop up for failure
  7919. DPF(APPerr, TEXT("MakeDOInfCopy:Failed to get WINDIR"));
  7920. hr = HRESULT_FROM_WIN32(GetLastError());
  7921. goto Exit;
  7922. }
  7923. ConcatenatePaths(szBackupDir,CLMT_BACKUP_DIR,ARRAYSIZE(szBackupDir));
  7924. hr = StringCchCopy(szDoInf,ARRAYSIZE(szDoInf),szBackupDir);
  7925. hr = StringCchCopy(szDoInfBackup,ARRAYSIZE(szDoInfBackup),szBackupDir);
  7926. ConcatenatePaths(szDoInf,TEXT("clmtdo.inf"),ARRAYSIZE(szDoInf));
  7927. ConcatenatePaths(szDoInfBackup,TEXT("clmtdo.bak"),ARRAYSIZE(szDoInfBackup));
  7928. if (!CopyFile(szDoInf,szDoInfBackup,FALSE))
  7929. {
  7930. DPF(APPerr, TEXT("MakeDOInfCopy:CopyFile failed"));
  7931. hr = HRESULT_FROM_WIN32(GetLastError());
  7932. goto Exit;
  7933. }
  7934. hr = S_OK;
  7935. Exit:
  7936. return hr;
  7937. }
  7938. VOID RemoveSubString(
  7939. LPTSTR lpSrcString,
  7940. LPCTSTR lpSubString
  7941. )
  7942. {
  7943. LPTSTR lpMatchedStr;
  7944. DWORD dwSubStrLen;
  7945. lpMatchedStr = StrStr(lpSrcString, lpSubString);
  7946. if (lpMatchedStr != NULL)
  7947. {
  7948. dwSubStrLen = lstrlen(lpSubString);
  7949. while (*(lpMatchedStr + dwSubStrLen) != TEXT('\0'))
  7950. {
  7951. *(lpMatchedStr) = *(lpMatchedStr + dwSubStrLen);
  7952. lpMatchedStr++;
  7953. }
  7954. *lpMatchedStr = TEXT('\0');
  7955. }
  7956. }