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

2841 lines
85 KiB

  1. #include <windowsx.h>
  2. #include <shlobj.h>
  3. #include <shlwapi.h>
  4. #include <shellapi.h>
  5. #include <stdio.h>
  6. #include <winioctl.h>
  7. #include "resource.h"
  8. #include "migutil.h"
  9. #include "migwiz.h"
  10. #include <tlhelp32.h>
  11. #include <tchar.h>
  12. #include <shlobjp.h>
  13. extern "C" {
  14. #include "ism.h"
  15. #include "modules.h"
  16. }
  17. PTSTR g_Explorer = NULL;
  18. /////////////////
  19. // definitions
  20. #ifndef ARRAYSIZE
  21. #define ARRAYSIZE(x) ((sizeof(x)) / (sizeof(x[0])))
  22. #endif
  23. CRITICAL_SECTION g_csDialogCritSection;
  24. BOOL g_fUberCancel;
  25. BOOL g_LogOffSystem = FALSE;
  26. BOOL g_RebootSystem = FALSE;
  27. BOOL g_OFStatus = FALSE;
  28. //////////////////////////////////////////////////////////////////////////////////////
  29. LPSTR _ConvertToAnsi(UINT cp, LPCWSTR pcwszSource)
  30. {
  31. // Locals
  32. HRESULT hr=S_OK;
  33. INT cchNarrow;
  34. INT cchWide;
  35. LPSTR pszDup=NULL;
  36. // No Source
  37. if (pcwszSource == NULL)
  38. goto exit;
  39. // Length
  40. cchWide = lstrlenW(pcwszSource) + 1;
  41. // Determine how much space is needed for translated widechar
  42. cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, NULL, 0, NULL, NULL);
  43. // Error
  44. if (cchNarrow == 0)
  45. goto exit;
  46. // Alloc temp buffer
  47. pszDup = (LPSTR)LocalAlloc(LPTR, cchNarrow + 1);
  48. if (NULL == pszDup)
  49. {
  50. goto exit;
  51. }
  52. // Do the actual translation
  53. cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, pszDup, cchNarrow + 1, NULL, NULL);
  54. // Error
  55. if (cchNarrow == 0)
  56. {
  57. if (NULL != pszDup)
  58. {
  59. free(pszDup);
  60. }
  61. goto exit;
  62. }
  63. exit:
  64. // Done
  65. return(pszDup);
  66. }
  67. //////////////////////////////////////////////////////////////////////////////////////
  68. LPWSTR _ConvertToUnicode(UINT cp, LPCSTR pcszSource)
  69. {
  70. // Locals
  71. HRESULT hr=S_OK;
  72. INT cchNarrow;
  73. INT cchWide;
  74. LPWSTR pwszDup=NULL;
  75. // No Source
  76. if (pcszSource == NULL)
  77. goto exit;
  78. // Length
  79. cchNarrow = lstrlenA(pcszSource) + 1;
  80. // Determine how much space is needed for translated widechar
  81. cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, NULL, 0);
  82. // Error
  83. if (cchWide == 0)
  84. goto exit;
  85. // Alloc temp buffer
  86. pwszDup = (LPWSTR)LocalAlloc(LPTR, cchWide * sizeof (WCHAR));
  87. if (NULL == pwszDup)
  88. {
  89. goto exit;
  90. }
  91. // Do the actual translation
  92. cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, pwszDup, cchWide+1);
  93. // Error
  94. if (cchWide == 0)
  95. {
  96. if (NULL != pwszDup)
  97. {
  98. free(pwszDup);
  99. }
  100. goto exit;
  101. }
  102. exit:
  103. // Done
  104. return pwszDup;
  105. }
  106. //////////////////////////////////////////////////////////////////////////////////////
  107. HRESULT _SHUnicodeToAnsi(LPWSTR pwszIn, LPSTR pszOut, UINT cchOut)
  108. {
  109. // Locals
  110. HRESULT hr = E_INVALIDARG;
  111. INT cchNarrow;
  112. INT cchWide;
  113. // No Source
  114. if (pwszIn && pszOut)
  115. {
  116. // Length
  117. cchWide = lstrlenW(pwszIn) + 1;
  118. // Determine how much space is needed for translated widechar
  119. cchNarrow = WideCharToMultiByte(CP_ACP, 0, pwszIn, cchWide, NULL, 0, NULL, NULL);
  120. // Error
  121. if (cchNarrow > 0)
  122. {
  123. // Do the actual translation
  124. cchNarrow = WideCharToMultiByte(CP_ACP, 0, pwszIn, cchWide, pszOut, cchNarrow + 1, NULL, NULL);
  125. if (cchNarrow)
  126. {
  127. hr = S_OK;
  128. }
  129. }
  130. }
  131. return hr;
  132. }
  133. //////////////////////////////////////////////////////////////////////////////////////
  134. HRESULT _SHAnsiToUnicode(LPSTR pszIn, LPWSTR pwszOut, UINT cchOut)
  135. {
  136. // Locals
  137. HRESULT hr = E_INVALIDARG;
  138. INT cchNarrow;
  139. INT cchWide;
  140. // No Source
  141. if (pszIn && pwszOut)
  142. {
  143. // Length
  144. cchNarrow = lstrlenA(pszIn) + 1;
  145. // Determine how much space is needed for translated widechar
  146. cchWide = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszIn, cchNarrow, NULL, 0);
  147. // Error
  148. if (cchWide > 0)
  149. {
  150. // Do the actual translation
  151. cchWide = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszIn, cchNarrow, pwszOut, cchWide+1);
  152. if (cchWide > 0)
  153. {
  154. hr = S_OK;
  155. }
  156. }
  157. }
  158. return hr;
  159. }
  160. //////////////////////////////////////////////////////////////////////////////////////
  161. #ifdef UNICODE
  162. #define _StrRetToBuf _StrRetToBufW
  163. #else
  164. #define _StrRetToBuf _StrRetToBufA
  165. #endif
  166. #ifdef NONAMELESSUNION
  167. #define NAMELESS_MEMBER(member) DUMMYUNIONNAME.##member
  168. #else
  169. #define NAMELESS_MEMBER(member) member
  170. #endif
  171. #define STRRET_OLESTR STRRET_WSTR // same as STRRET_WSTR
  172. #define STRRET_OFFPTR(pidl,lpstrret) ((LPSTR)((LPBYTE)(pidl)+(lpstrret)->NAMELESS_MEMBER(uOffset)))
  173. STDAPI _StrRetToBufA(STRRET *psr, LPCITEMIDLIST pidl, LPSTR pszBuf, UINT cchBuf)
  174. {
  175. HRESULT hres = E_FAIL;
  176. switch (psr->uType)
  177. {
  178. case STRRET_WSTR:
  179. {
  180. LPWSTR pszStr = psr->pOleStr; // temp copy because SHUnicodeToAnsi may overwrite buffer
  181. if (pszStr)
  182. {
  183. _SHUnicodeToAnsi(pszStr, pszBuf, cchBuf);
  184. CoTaskMemFree(pszStr);
  185. // Make sure no one thinks things are allocated still
  186. psr->uType = STRRET_CSTR;
  187. psr->cStr[0] = 0;
  188. hres = S_OK;
  189. }
  190. }
  191. break;
  192. case STRRET_CSTR:
  193. StrCpyNA (pszBuf, psr->cStr, cchBuf);
  194. hres = S_OK;
  195. break;
  196. case STRRET_OFFSET:
  197. if (pidl)
  198. {
  199. StrCpyNA (pszBuf, STRRET_OFFPTR(pidl, psr), cchBuf);
  200. hres = S_OK;
  201. }
  202. break;
  203. }
  204. if (FAILED(hres) && cchBuf)
  205. *pszBuf = 0;
  206. return hres;
  207. }
  208. STDAPI _StrRetToBufW(STRRET *psr, LPCITEMIDLIST pidl, LPWSTR pszBuf, UINT cchBuf)
  209. {
  210. HRESULT hres = E_FAIL;
  211. switch (psr->uType)
  212. {
  213. case STRRET_WSTR:
  214. {
  215. LPWSTR pwszTmp = psr->pOleStr;
  216. if (pwszTmp)
  217. {
  218. StrCpyNW(pszBuf, pwszTmp, cchBuf);
  219. CoTaskMemFree(pwszTmp);
  220. // Make sure no one thinks things are allocated still
  221. psr->uType = STRRET_CSTR;
  222. psr->cStr[0] = 0;
  223. hres = S_OK;
  224. }
  225. }
  226. break;
  227. case STRRET_CSTR:
  228. _SHAnsiToUnicode(psr->cStr, pszBuf, cchBuf);
  229. hres = S_OK;
  230. break;
  231. case STRRET_OFFSET:
  232. if (pidl)
  233. {
  234. _SHAnsiToUnicode(STRRET_OFFPTR(pidl, psr), pszBuf, cchBuf);
  235. hres = S_OK;
  236. }
  237. break;
  238. }
  239. if (FAILED(hres) && cchBuf)
  240. *pszBuf = 0;
  241. return hres;
  242. }
  243. //////////////////////////////////////////////////////////////////////////////////////
  244. INT_PTR _ExclusiveDialogBox(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc)
  245. {
  246. INT_PTR iRetVal = -1;
  247. EnterCriticalSection(&g_csDialogCritSection);
  248. if (!g_fUberCancel)
  249. {
  250. iRetVal = DialogBoxParam(hInstance, lpTemplate, hWndParent, lpDialogFunc, (LPARAM)hWndParent);
  251. }
  252. LeaveCriticalSection(&g_csDialogCritSection);
  253. return iRetVal;
  254. }
  255. int _ExclusiveMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
  256. {
  257. int iRetVal = -1;
  258. EnterCriticalSection(&g_csDialogCritSection);
  259. if (!g_fUberCancel)
  260. {
  261. iRetVal = MessageBox(hWnd, lpText, lpCaption, uType);
  262. }
  263. LeaveCriticalSection(&g_csDialogCritSection);
  264. return iRetVal;
  265. }
  266. //////////////////////////////////////////////////////////////////////////////////////
  267. int _ComboBoxEx_AddString(HWND hwndBox, LPTSTR ptsz)
  268. {
  269. COMBOBOXEXITEM item = {0};
  270. item.mask = CBEIF_TEXT;
  271. item.iItem = ComboBox_GetCount(hwndBox);
  272. item.pszText = ptsz;
  273. return (INT) SendMessage(hwndBox, CBEM_INSERTITEM, 0, (LONG_PTR)&item);
  274. }
  275. //////////////////////////////////////////////////////////////////////////////////////
  276. int _ComboBoxEx_SetItemData(HWND hwndBox, UINT iDex, LPARAM lParam)
  277. {
  278. COMBOBOXEXITEM item = {0};
  279. item.mask = CBEIF_LPARAM;
  280. item.iItem = iDex;
  281. item.lParam = lParam;
  282. return (INT) SendMessage(hwndBox, CBEM_SETITEM, 0, (LONG_PTR)&item);
  283. }
  284. //////////////////////////////////////////////////////////////////////////////////////
  285. int _ComboBoxEx_SetIcon(HWND hwndBox, LPTSTR sz, UINT iDex)
  286. {
  287. SHFILEINFO sfi = {0};
  288. COMBOBOXEXITEM item = {0};
  289. DWORD dwFlags = SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES;
  290. if (SHGetFileInfo(sz, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), dwFlags)) {
  291. item.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
  292. item.iItem = iDex;
  293. item.iImage = sfi.iIcon;
  294. item.iSelectedImage = sfi.iIcon;
  295. return (INT) SendMessage(hwndBox, CBEM_SETITEM, 0, (LONG_PTR)&item);
  296. }
  297. return -1;
  298. }
  299. //////////////////////////////////////////////////////////////////////////////////////
  300. int _GetRemovableDriveCount()
  301. {
  302. int iCount = 0;
  303. TCHAR szDrive[4] = TEXT("A:\\");
  304. for (UINT uiCount = 0; uiCount < 26; uiCount++)
  305. {
  306. szDrive[0] = TEXT('A') + uiCount;
  307. if (DRIVE_REMOVABLE == GetDriveType(szDrive))
  308. {
  309. iCount++;
  310. }
  311. }
  312. return iCount;
  313. }
  314. //////////////////////////////////////////////////////////////////////////////////////
  315. TCHAR _GetRemovableDrive(int iDex)
  316. {
  317. int iCount = iDex;
  318. TCHAR szDrive[4] = TEXT("?:\\");
  319. for (UINT uiCount = 0; uiCount < 26; uiCount++)
  320. {
  321. szDrive[0] = TEXT('A') + uiCount;
  322. if (DRIVE_REMOVABLE == GetDriveType(szDrive))
  323. {
  324. if (!(iCount--))
  325. {
  326. return szDrive[0];
  327. }
  328. }
  329. }
  330. // ASSERT(FALSE);
  331. return '0'; // ERROR
  332. }
  333. //////////////////////////////////////////////////////////////////////////////////////
  334. LPTSTR _GetRemovableDrivePretty(int iDex)
  335. {
  336. HRESULT hr;
  337. LPTSTR pszRetVal = NULL;
  338. WCHAR wszDrive[4] = L"A:\\";
  339. wszDrive[0] = L'A' + _GetRemovableDrive(iDex) - TEXT('A');
  340. IShellFolder* psfDesktop;
  341. hr = SHGetDesktopFolder(&psfDesktop);
  342. if (SUCCEEDED(hr))
  343. {
  344. LPITEMIDLIST pidlDrive;
  345. hr = psfDesktop->ParseDisplayName(NULL, NULL, wszDrive, NULL, &pidlDrive, NULL);
  346. if (SUCCEEDED(hr))
  347. {
  348. STRRET strret;
  349. hr = psfDesktop->GetDisplayNameOf(pidlDrive, SHGDN_INFOLDER, &strret);
  350. if (SUCCEEDED(hr))
  351. {
  352. TCHAR szDisplayName[MAX_PATH];
  353. if (SUCCEEDED(_StrRetToBuf(&strret, pidlDrive, szDisplayName, ARRAYSIZE(szDisplayName))))
  354. {
  355. pszRetVal = StrDup(szDisplayName);
  356. }
  357. }
  358. }
  359. }
  360. return pszRetVal;
  361. }
  362. //////////////////////////////////////////////////////////////////////////////////////
  363. BOOL _IsRemovableOrCDDrive(TCHAR chDrive)
  364. {
  365. UINT result = 0;
  366. if ( (chDrive >= TEXT('A') && chDrive <= TEXT('Z')) || (chDrive >= TEXT('a') && chDrive <= TEXT('z')))
  367. {
  368. TCHAR szDrive[4] = TEXT("A:\\");
  369. szDrive[0] = chDrive;
  370. result = GetDriveType (szDrive);
  371. return ((result == DRIVE_REMOVABLE) || (result == DRIVE_CDROM));
  372. }
  373. return FALSE;
  374. }
  375. BOOL _IsValidDrive(TCHAR chDrive)
  376. {
  377. UINT result;
  378. if ( (chDrive >= TEXT('A') && chDrive <= TEXT('Z')) || (chDrive >= TEXT('a') && chDrive <= TEXT('z')))
  379. {
  380. TCHAR szDrive[4] = TEXT("A:\\");
  381. szDrive[0] = chDrive;
  382. result = GetDriveType(szDrive);
  383. if ((result == DRIVE_UNKNOWN) ||
  384. (result == DRIVE_NO_ROOT_DIR)
  385. ) {
  386. return FALSE;
  387. }
  388. return TRUE;
  389. }
  390. return FALSE;
  391. }
  392. BOOL _IsValidStorePath(PCTSTR pszStore)
  393. {
  394. return (((pszStore[1] == TEXT(':')) && (pszStore[2] == TEXT('\\')) && (_IsValidDrive (pszStore [0]))) ||
  395. ((pszStore[0] == TEXT('\\')) && (pszStore[1] == TEXT('\\')) && (_tcschr (pszStore + 2, TEXT('\\')) != NULL)));
  396. }
  397. BOOL _CreateFullDirectory(PCTSTR pszPath)
  398. {
  399. TCHAR pathCopy [MAX_PATH];
  400. PTSTR p;
  401. BOOL b = TRUE;
  402. StrCpyN (pathCopy, pszPath, ARRAYSIZE(pathCopy));
  403. //
  404. // Advance past first directory
  405. //
  406. if (pathCopy[1] == TEXT(':') && pathCopy[2] == TEXT('\\')) {
  407. //
  408. // <drive>:\ case
  409. //
  410. p = _tcschr (&pathCopy[3], TEXT('\\'));
  411. } else if (pathCopy[0] == TEXT('\\') && pathCopy[1] == TEXT('\\')) {
  412. //
  413. // UNC case
  414. //
  415. p = _tcschr (pathCopy + 2, TEXT('\\'));
  416. if (p) {
  417. p = _tcschr (p + 1, TEXT('\\'));
  418. if (p) {
  419. p = _tcsinc (p);
  420. if (p) {
  421. p = _tcschr (p, TEXT('\\'));
  422. }
  423. }
  424. }
  425. } else {
  426. //
  427. // Relative dir case
  428. //
  429. p = _tcschr (pathCopy, TEXT('\\'));
  430. }
  431. //
  432. // Make all directories along the path
  433. //
  434. while (p) {
  435. *p = 0;
  436. b = CreateDirectory (pathCopy, NULL);
  437. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  438. b = TRUE;
  439. }
  440. if (!b) {
  441. break;
  442. }
  443. *p = TEXT('\\');
  444. p = _tcsinc (p);
  445. if (p) {
  446. p = _tcschr (p + 1, TEXT('\\'));
  447. }
  448. }
  449. //
  450. // At last, make the FullPath directory
  451. //
  452. if (b) {
  453. b = CreateDirectory (pathCopy, NULL);
  454. if (!b && GetLastError() == ERROR_ALREADY_EXISTS) {
  455. b = TRUE;
  456. }
  457. }
  458. return b;
  459. }
  460. PTSTR
  461. pGoBack (
  462. IN PTSTR LastChar,
  463. IN PTSTR FirstChar,
  464. IN UINT NumWacks
  465. )
  466. {
  467. LastChar = _tcsdec (FirstChar, LastChar);
  468. while (NumWacks && LastChar && (LastChar >= FirstChar)) {
  469. if (_tcsnextc (LastChar) == TEXT('\\')) {
  470. NumWacks --;
  471. }
  472. LastChar = _tcsdec (FirstChar, LastChar);
  473. }
  474. if (NumWacks) {
  475. return NULL;
  476. }
  477. return LastChar + 2;
  478. }
  479. UINT
  480. pCountDots (
  481. IN PCTSTR PathSeg
  482. )
  483. {
  484. UINT numDots = 0;
  485. while (PathSeg && *PathSeg) {
  486. if (_tcsnextc (PathSeg) != TEXT('.')) {
  487. return 0;
  488. }
  489. numDots ++;
  490. PathSeg = _tcsinc (PathSeg);
  491. }
  492. return numDots;
  493. }
  494. PCTSTR
  495. _SanitizePath (
  496. IN PCTSTR FileSpec
  497. )
  498. {
  499. TCHAR pathSeg [MAX_PATH];
  500. PCTSTR wackPtr;
  501. UINT dotNr;
  502. PTSTR newPath = (PTSTR)IsmDuplicateString (FileSpec);
  503. PTSTR newPathPtr = newPath;
  504. BOOL firstPass = TRUE;
  505. UINT max;
  506. BOOL removeLastWack = FALSE;
  507. do {
  508. removeLastWack = FALSE;
  509. ZeroMemory (pathSeg, sizeof (pathSeg));
  510. wackPtr = _tcschr (FileSpec, TEXT('\\'));
  511. if (wackPtr) {
  512. if (firstPass && (wackPtr == FileSpec)) {
  513. // this one starts with a wack, let's see if we have double wacks
  514. wackPtr = _tcsinc (wackPtr);
  515. if (!wackPtr) {
  516. IsmReleaseMemory (newPath);
  517. return NULL;
  518. }
  519. if (_tcsnextc (wackPtr) == TEXT('\\')) {
  520. // this one starts with a double wack
  521. wackPtr = _tcsinc (wackPtr);
  522. if (!wackPtr) {
  523. IsmReleaseMemory (newPath);
  524. return NULL;
  525. }
  526. wackPtr = _tcschr (wackPtr, TEXT('\\'));
  527. } else {
  528. wackPtr = _tcschr (wackPtr, TEXT('\\'));
  529. }
  530. }
  531. firstPass = FALSE;
  532. if (wackPtr) {
  533. max = (wackPtr - FileSpec) * sizeof (TCHAR);
  534. CopyMemory (pathSeg, FileSpec, min (MAX_PATH * sizeof (TCHAR), max));
  535. FileSpec = _tcsinc (wackPtr);
  536. } else {
  537. max = _tcslen (FileSpec) * sizeof (TCHAR);
  538. CopyMemory (pathSeg, FileSpec, min (MAX_PATH * sizeof (TCHAR), max));
  539. }
  540. } else {
  541. max = _tcslen (FileSpec) * sizeof (TCHAR);
  542. if (max == 0) {
  543. removeLastWack = TRUE;
  544. }
  545. CopyMemory (pathSeg, FileSpec, min (MAX_PATH * sizeof (TCHAR), max));
  546. }
  547. if (*pathSeg) {
  548. dotNr = pCountDots (pathSeg);
  549. if (dotNr>1) {
  550. newPathPtr = pGoBack (newPathPtr, newPath, dotNr);
  551. if (newPathPtr == NULL) {
  552. IsmReleaseMemory (newPath);
  553. return NULL;
  554. }
  555. } else if (dotNr != 1) {
  556. _tcscpy (newPathPtr, pathSeg);
  557. newPathPtr = _tcschr (newPathPtr, 0);
  558. if (wackPtr) {
  559. *newPathPtr = TEXT('\\');
  560. //we increment this because we know that \ is a single byte character.
  561. newPathPtr ++;
  562. }
  563. } else {
  564. removeLastWack = TRUE;
  565. }
  566. }
  567. } while (wackPtr);
  568. if (removeLastWack && (newPathPtr > newPath)) {
  569. newPathPtr --;
  570. }
  571. *newPathPtr = 0;
  572. return newPath;
  573. }
  574. BOOL _IsValidStore(LPTSTR pszStore, BOOL bCreate, HINSTANCE hinst, HWND hwnd)
  575. {
  576. TCHAR szSerialStr[] = TEXT("COM");
  577. TCHAR szParallelStr[] = TEXT("LPT");
  578. PTSTR lpExpStore;
  579. PCTSTR sanitizedStore;
  580. BOOL fValid = FALSE;
  581. //
  582. // Skip past leading space, since PathIsDirectory() on Win9x
  583. // incorrectly assumes spaces are a valid dir.
  584. //
  585. while (_istspace (*pszStore))
  586. pszStore++;
  587. //
  588. // No relative paths allowed.
  589. //
  590. if (*pszStore == TEXT('.'))
  591. return FALSE;
  592. if ((_tcsnicmp (pszStore, szSerialStr, (sizeof (szSerialStr) / sizeof (TCHAR)) - 1) == 0) ||
  593. (_tcsnicmp (pszStore, szParallelStr, (sizeof (szParallelStr) / sizeof (TCHAR)) - 1) == 0)
  594. ) {
  595. return TRUE;
  596. }
  597. lpExpStore = (PTSTR)IsmExpandEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, pszStore, NULL);
  598. sanitizedStore = _SanitizePath (lpExpStore);
  599. if (sanitizedStore) {
  600. if (PathIsDirectory(sanitizedStore)) // if a normal directory
  601. {
  602. fValid = TRUE;
  603. }
  604. else if (lstrlen(sanitizedStore) == 3 && sanitizedStore[1] == TEXT(':') && sanitizedStore[2] == TEXT('\\') && _IsRemovableOrCDDrive(sanitizedStore[0]))
  605. {
  606. fValid = TRUE;
  607. }
  608. else if (lstrlen(sanitizedStore) == 2 && sanitizedStore[1] == TEXT(':') && _IsRemovableOrCDDrive(sanitizedStore[0]))
  609. {
  610. fValid = TRUE;
  611. }
  612. else
  613. {
  614. if ((bCreate) && (_IsValidStorePath (sanitizedStore))) {
  615. TCHAR szTitle[MAX_LOADSTRING];
  616. TCHAR szLoadString[MAX_LOADSTRING];
  617. LoadString(hinst, IDS_MIGWIZTITLE, szTitle, ARRAYSIZE(szTitle));
  618. LoadString(hinst, IDS_ASKCREATEDIR, szLoadString, ARRAYSIZE(szLoadString));
  619. if (_ExclusiveMessageBox(hwnd, szLoadString, szTitle, MB_YESNO) == IDYES) {
  620. if (_CreateFullDirectory (sanitizedStore)) {
  621. fValid = TRUE;
  622. }
  623. }
  624. }
  625. }
  626. if (fValid) {
  627. _tcsncpy (pszStore, sanitizedStore, MAX_PATH);
  628. }
  629. IsmReleaseMemory (sanitizedStore);
  630. sanitizedStore = NULL;
  631. }
  632. IsmReleaseMemory (lpExpStore);
  633. return fValid;
  634. }
  635. //////////////////////////////////////////////////////////////////////////////////////
  636. INT _ComboBoxEx_AddDrives(HWND hwndBox)
  637. {
  638. INT result = -1;
  639. ComboBox_ResetContent(hwndBox);
  640. WCHAR wszDrive[4] = L"A:\\";
  641. TCHAR szDrive[4] = TEXT("A:\\");
  642. for (UINT uiCount = 0; uiCount < (UINT)_GetRemovableDriveCount(); uiCount++)
  643. {
  644. szDrive[0] = _GetRemovableDrive(uiCount);
  645. int iDex = _ComboBoxEx_AddString(hwndBox, _GetRemovableDrivePretty(uiCount));
  646. _ComboBoxEx_SetIcon(hwndBox, szDrive, iDex);
  647. _ComboBoxEx_SetItemData(hwndBox, iDex, (LPARAM)StrDup(szDrive));
  648. result = 0;
  649. }
  650. ComboBox_SetCurSel(hwndBox, result);
  651. return result;
  652. }
  653. //////////////////////////////////////////////////////////////////////////////////////
  654. BOOL
  655. pIsComPortAccessible (
  656. PCTSTR ComPort
  657. )
  658. {
  659. HANDLE comPortHandle = NULL;
  660. comPortHandle = CreateFile (ComPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  661. if (comPortHandle != INVALID_HANDLE_VALUE) {
  662. CloseHandle (comPortHandle);
  663. return TRUE;
  664. }
  665. return FALSE;
  666. }
  667. INT _ComboBoxEx_AddCOMPorts(HWND hwndBox, INT SelectedPort)
  668. {
  669. INT iDex;
  670. INT index = 1;
  671. INT added = -1;
  672. TCHAR comPort [] = TEXT("COM0");
  673. if (hwndBox) {
  674. // clear the combo box content
  675. SendMessage (hwndBox, CB_RESETCONTENT, 0, 0);
  676. }
  677. while (index < 10) {
  678. comPort [ARRAYSIZE(comPort) - 2] ++;
  679. if (pIsComPortAccessible (comPort)) {
  680. if (hwndBox) {
  681. iDex = SendMessage (hwndBox, CB_ADDSTRING, 0, (LPARAM)comPort);
  682. SendMessage (hwndBox, CB_SETITEMDATA, (WPARAM)iDex, (LPARAM)StrDup(comPort));
  683. }
  684. added ++;
  685. }
  686. index ++;
  687. }
  688. if (added == -1) {
  689. return -1;
  690. }
  691. if ((added >= SelectedPort) && (SelectedPort != -1)) {
  692. if (hwndBox) {
  693. ComboBox_SetCurSel(hwndBox, SelectedPort);
  694. }
  695. return SelectedPort;
  696. }
  697. if (hwndBox) {
  698. // We want nothing to be selected in this combo box, this
  699. // is intentional.
  700. ComboBox_SetCurSel(hwndBox, -1);
  701. }
  702. return 0;
  703. }
  704. //////////////////////////////////////////////////////////////////////////////////////
  705. int _GetIcon(LPTSTR psz)
  706. {
  707. SHFILEINFO sfi = {0};
  708. SHGetFileInfo(psz, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  709. return sfi.iIcon;
  710. }
  711. //////////////////////////////////////////////////////////////////////////////////////
  712. HRESULT _ListView_AddDrives(HWND hwndList, LPTSTR pszNetworkName)
  713. {
  714. HRESULT hr = E_FAIL;
  715. if (ListView_DeleteAllItems(hwndList))
  716. {
  717. LVITEM item = {0};
  718. item.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT;
  719. if (pszNetworkName)
  720. {
  721. item.iItem = 0; // first item
  722. item.pszText = pszNetworkName;
  723. item.iImage = 0; // ISSUE: 0 is icon for sharing, is there a better way to do this?
  724. item.lParam = NULL;
  725. ListView_InsertItem(hwndList, &item);
  726. }
  727. IShellFolder* psfDesktop;
  728. hr = SHGetDesktopFolder(&psfDesktop);
  729. if (SUCCEEDED(hr))
  730. {
  731. WCHAR wszDrive[4] = L"?:\\";
  732. TCHAR tszDrive[4] = TEXT("?:\\");
  733. for (int iDrive = 0; iDrive < _GetRemovableDriveCount(); iDrive++)
  734. {
  735. tszDrive[0] = _GetRemovableDrive(iDrive);
  736. wszDrive[0] = L'A' + tszDrive[0] - TEXT('A');
  737. LPITEMIDLIST pidlDrive;
  738. hr = psfDesktop->ParseDisplayName(NULL, NULL, wszDrive, NULL, &pidlDrive, NULL);
  739. if (SUCCEEDED(hr))
  740. {
  741. STRRET strret;
  742. hr = psfDesktop->GetDisplayNameOf(pidlDrive, SHGDN_INFOLDER, &strret);
  743. if (SUCCEEDED(hr))
  744. {
  745. TCHAR szDisplayName[MAX_PATH];
  746. hr = _StrRetToBuf(&strret, pidlDrive, szDisplayName, ARRAYSIZE(szDisplayName));
  747. if (SUCCEEDED(hr))
  748. {
  749. item.iItem = 27; // this will force adding at the end
  750. item.pszText = szDisplayName;
  751. item.iImage = _GetIcon(tszDrive);
  752. item.lParam = (LPARAM)StrDup(tszDrive);
  753. ListView_InsertItem(hwndList, &item);
  754. }
  755. }
  756. }
  757. }
  758. }
  759. }
  760. return S_OK;
  761. }
  762. //////////////////////////////////////////////////////////////////////////////////////
  763. HRESULT _CreateAnimationCtrl(HWND hwndDlg, HINSTANCE hinst, UINT idMarker, UINT idAnim, UINT idAvi, HWND* pHwndAnim)
  764. {
  765. HWND hwndAnim = NULL;
  766. RECT rc, rc1, rc2, rc3;
  767. POINT pt31, pt32;
  768. LONG tempXY = 0;
  769. PWORD tempX, tempY;
  770. POINT pt;
  771. // Create the animation control.
  772. hwndAnim = Animate_Create(hwndDlg, (ULONG_PTR) idAnim, WS_CHILD | ACS_TRANSPARENT, hinst);
  773. // Get the screen coordinates of the specified control button.
  774. GetWindowRect(GetDlgItem(hwndDlg, idMarker), &rc);
  775. // Get the screen coordinates of the specified control button.
  776. GetWindowRect(hwndAnim, &rc1);
  777. // Convert the coordinates of the lower-left corner to
  778. // client coordinates.
  779. pt.x = rc.left;
  780. pt.y = rc.bottom;
  781. ScreenToClient(hwndDlg, &pt);
  782. // Position the animation control below the Stop button.
  783. SetWindowPos(hwndAnim, 0, pt.x, pt.y + 20, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  784. // Get the screen coordinates of the specified control button.
  785. GetWindowRect(hwndAnim, &rc2);
  786. // Open the AVI clip, and show the animation control.
  787. Animate_Open(hwndAnim, MAKEINTRESOURCE(idAvi));
  788. ShowWindow(hwndAnim, SW_SHOW);
  789. Animate_Play(hwndAnim, 0, -1, -1);
  790. // Get the screen coordinates of the specified control button.
  791. GetWindowRect(hwndAnim, &rc3);
  792. pt31.x = rc3.left;
  793. pt31.y = rc3.top;
  794. pt32.x = rc3.right;
  795. pt32.y = rc3.bottom;
  796. ScreenToClient(hwndDlg, &pt31);
  797. ScreenToClient(hwndDlg, &pt32);
  798. rc3.left = pt31.x;
  799. rc3.top = pt31.y;
  800. rc3.right = pt32.x;
  801. rc3.bottom = pt32.y;
  802. tempXY = GetDialogBaseUnits ();
  803. tempX = (PWORD)(&tempXY);
  804. tempY = tempX + 1;
  805. rc3.left = MulDiv (rc3.left, 4, *tempX);
  806. rc3.right = MulDiv (rc3.right, 4, *tempX);
  807. rc3.top = MulDiv (rc3.top, 8, *tempY);
  808. rc3.bottom = MulDiv (rc3.bottom, 8, *tempY);
  809. *pHwndAnim = hwndAnim;
  810. return S_OK;
  811. }
  812. //////////////////////////////////////////////////////////////////////////////////////
  813. #define USER_SHELL_FOLDERS \
  814. DEFMAC(CSIDL_ADMINTOOLS, TEXT("Administrative Tools"), -1, IDS_CSIDL_ADMINTOOLS) \
  815. DEFMAC(CSIDL_ALTSTARTUP, TEXT("AltStartup"), -1, IDS_CSIDL_ALTSTARTUP) \
  816. DEFMAC(CSIDL_APPDATA, TEXT("AppData"), -1, IDS_CSIDL_APPDATA) \
  817. DEFMAC(CSIDL_BITBUCKET, TEXT("RecycleBinFolder"), -1, IDS_CSIDL_BITBUCKET) \
  818. DEFMAC(CSIDL_CONNECTIONS, TEXT("ConnectionsFolder"), -1, IDS_CSIDL_CONNECTIONS) \
  819. DEFMAC(CSIDL_CONTROLS, TEXT("ControlPanelFolder"), -1, IDS_CSIDL_CONTROLS) \
  820. DEFMAC(CSIDL_COOKIES, TEXT("Cookies"), -1, IDS_CSIDL_COOKIES) \
  821. DEFMAC(CSIDL_DESKTOP, TEXT("Desktop"), -1, IDS_CSIDL_DESKTOP) \
  822. DEFMAC(CSIDL_DESKTOPDIRECTORY, TEXT("Desktop"), -1, IDS_CSIDL_DESKTOPDIRECTORY) \
  823. DEFMAC(CSIDL_DRIVES, TEXT("DriveFolder"), -1, IDS_CSIDL_DRIVES) \
  824. DEFMAC(CSIDL_FAVORITES, TEXT("Favorites"), -1, IDS_CSIDL_FAVORITES) \
  825. DEFMAC(CSIDL_FONTS, TEXT("Fonts"), -1, IDS_CSIDL_FONTS) \
  826. DEFMAC(CSIDL_HISTORY, TEXT("History"), -1, IDS_CSIDL_HISTORY) \
  827. DEFMAC(CSIDL_INTERNET, TEXT("InternetFolder"), -1, IDS_CSIDL_INTERNET) \
  828. DEFMAC(CSIDL_INTERNET_CACHE, TEXT("Cache"), -1, IDS_CSIDL_INTERNET_CACHE) \
  829. DEFMAC(CSIDL_LOCAL_APPDATA, TEXT("Local AppData"), -1, IDS_CSIDL_LOCAL_APPDATA) \
  830. DEFMAC(CSIDL_MYDOCUMENTS, TEXT("My Documents"), -1, IDS_CSIDL_MYDOCUMENTS) \
  831. DEFMAC(CSIDL_MYMUSIC, TEXT("My Music"), -1, IDS_CSIDL_MYMUSIC) \
  832. DEFMAC(CSIDL_MYPICTURES, TEXT("My Pictures"), -1, IDS_CSIDL_MYPICTURES) \
  833. DEFMAC(CSIDL_MYVIDEO, TEXT("My Video"), -1, IDS_CSIDL_MYVIDEO) \
  834. DEFMAC(CSIDL_NETHOOD, TEXT("NetHood"), -1, IDS_CSIDL_NETHOOD) \
  835. DEFMAC(CSIDL_NETWORK, TEXT("NetworkFolder"), -1, IDS_CSIDL_NETWORK) \
  836. DEFMAC(CSIDL_PERSONAL, TEXT("Personal"), -1, IDS_CSIDL_PERSONAL) \
  837. DEFMAC(CSIDL_PROFILE, TEXT("Profile"), -1, IDS_CSIDL_PROFILE) \
  838. DEFMAC(CSIDL_PROGRAM_FILES, TEXT("ProgramFiles"), -1, IDS_CSIDL_PROGRAM_FILES) \
  839. DEFMAC(CSIDL_PROGRAM_FILESX86, TEXT("ProgramFilesX86"), -1, IDS_CSIDL_PROGRAM_FILESX86) \
  840. DEFMAC(CSIDL_PROGRAM_FILES_COMMON, TEXT("CommonProgramFiles"), -1, IDS_CSIDL_PROGRAM_FILES_COMMON) \
  841. DEFMAC(CSIDL_PROGRAM_FILES_COMMONX86, TEXT("CommonProgramFilesX86"), -1, IDS_CSIDL_PROGRAM_FILES_COMMONX86) \
  842. DEFMAC(CSIDL_PROGRAMS, TEXT("Programs"), -1, IDS_CSIDL_PROGRAMS) \
  843. DEFMAC(CSIDL_RECENT, TEXT("Recent"), -1, IDS_CSIDL_RECENT) \
  844. DEFMAC(CSIDL_SENDTO, TEXT("SendTo"), -1, IDS_CSIDL_SENDTO) \
  845. DEFMAC(CSIDL_STARTMENU, TEXT("Start Menu"), -1, IDS_CSIDL_STARTMENU) \
  846. DEFMAC(CSIDL_STARTUP, TEXT("Startup"), -1, IDS_CSIDL_STARTUP) \
  847. DEFMAC(CSIDL_SYSTEM, TEXT("System"), -1, IDS_CSIDL_SYSTEM) \
  848. DEFMAC(CSIDL_SYSTEMX86, TEXT("SystemX86"), -1, IDS_CSIDL_SYSTEMX86) \
  849. DEFMAC(CSIDL_TEMPLATES, TEXT("Templates"), -1, IDS_CSIDL_TEMPLATES) \
  850. DEFMAC(CSIDL_WINDOWS, TEXT("Windows"), -1, IDS_CSIDL_WINDOWS) \
  851. #define COMMON_SHELL_FOLDERS \
  852. DEFMAC(CSIDL_COMMON_ADMINTOOLS, TEXT("Common Administrative Tools"), CSIDL_ADMINTOOLS, IDS_CSIDL_COMMON_ADMINTOOLS) \
  853. DEFMAC(CSIDL_COMMON_ALTSTARTUP, TEXT("Common AltStartup"), CSIDL_ALTSTARTUP, IDS_CSIDL_COMMON_ALTSTARTUP) \
  854. DEFMAC(CSIDL_COMMON_APPDATA, TEXT("Common AppData"), CSIDL_APPDATA, IDS_CSIDL_COMMON_APPDATA) \
  855. DEFMAC(CSIDL_COMMON_DESKTOPDIRECTORY, TEXT("Common Desktop"), CSIDL_DESKTOP, IDS_CSIDL_COMMON_DESKTOPDIRECTORY) \
  856. DEFMAC(CSIDL_COMMON_DOCUMENTS, TEXT("Common Documents"), CSIDL_PERSONAL, IDS_CSIDL_COMMON_DOCUMENTS) \
  857. DEFMAC(CSIDL_COMMON_FAVORITES, TEXT("Common Favorites"), CSIDL_FAVORITES, IDS_CSIDL_COMMON_FAVORITES) \
  858. DEFMAC(CSIDL_COMMON_PROGRAMS, TEXT("Common Programs"), CSIDL_PROGRAMS, IDS_CSIDL_COMMON_PROGRAMS) \
  859. DEFMAC(CSIDL_COMMON_STARTMENU, TEXT("Common Start Menu"), CSIDL_STARTMENU, IDS_CSIDL_COMMON_STARTMENU) \
  860. DEFMAC(CSIDL_COMMON_STARTUP, TEXT("Common Startup"), CSIDL_STARTUP, IDS_CSIDL_COMMON_STARTUP) \
  861. DEFMAC(CSIDL_COMMON_TEMPLATES, TEXT("Common Templates"), CSIDL_TEMPLATES, IDS_CSIDL_COMMON_TEMPLATES) \
  862. //
  863. // This is the structure used for handling CSIDLs
  864. //
  865. typedef struct {
  866. INT DirId;
  867. PCTSTR DirStr;
  868. INT AltDirId;
  869. UINT DirResId;
  870. BOOL DirUser;
  871. } CSIDL_STRUCT, *PCSIDL_STRUCT;
  872. #define DEFMAC(did,dstr,adid,rid) {did,dstr,adid,rid,TRUE},
  873. static CSIDL_STRUCT g_UserShellFolders[] = {
  874. USER_SHELL_FOLDERS
  875. {-1, NULL, -1, 0, FALSE}
  876. };
  877. #undef DEFMAC
  878. #define DEFMAC(did,dstr,adid,rid) {did,dstr,adid,rid,FALSE},
  879. static CSIDL_STRUCT g_CommonShellFolders[] = {
  880. COMMON_SHELL_FOLDERS
  881. {-1, NULL, -1, 0, FALSE}
  882. };
  883. #undef DEFMAC
  884. PTSTR
  885. pFindSfPath (
  886. IN PCTSTR FolderStr,
  887. IN BOOL UserFolder
  888. )
  889. {
  890. HKEY key = NULL;
  891. PTSTR data;
  892. PTSTR expData;
  893. DWORD expDataSize;
  894. PTSTR result = NULL;
  895. LONG lResult;
  896. DWORD dataType;
  897. DWORD dataSize;
  898. if (!result) {
  899. if (UserFolder) {
  900. lResult = RegOpenKey (HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"), &key);
  901. } else {
  902. lResult = RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"), &key);
  903. }
  904. if ((lResult == ERROR_SUCCESS) && key) {
  905. dataSize = 0;
  906. lResult = RegQueryValueEx (key, FolderStr, NULL, &dataType, NULL, &dataSize);
  907. if ((lResult == ERROR_SUCCESS) &&
  908. ((dataType == REG_SZ) || (dataType == REG_EXPAND_SZ))
  909. ) {
  910. data = (PTSTR)LocalAlloc (LPTR, dataSize);
  911. if (data) {
  912. lResult = RegQueryValueEx (key, FolderStr, NULL, &dataType, (LPBYTE)data, &dataSize);
  913. if (lResult == ERROR_SUCCESS) {
  914. expDataSize = ExpandEnvironmentStrings (data, NULL, 0);
  915. if (expDataSize) {
  916. expData = (PTSTR)LocalAlloc (LPTR, (expDataSize + 1) * sizeof (TCHAR));
  917. expDataSize = ExpandEnvironmentStrings (data, expData, expDataSize);
  918. if (!expDataSize) {
  919. LocalFree (expData);
  920. expData = NULL;
  921. }
  922. }
  923. if (expDataSize) {
  924. result = expData;
  925. LocalFree (data);
  926. } else {
  927. result = data;
  928. }
  929. } else {
  930. LocalFree (data);
  931. }
  932. }
  933. }
  934. CloseHandle (key);
  935. }
  936. }
  937. if (result && !(*result)) {
  938. LocalFree (result);
  939. result = NULL;
  940. }
  941. if (!result) {
  942. if (UserFolder) {
  943. lResult = RegOpenKey (HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"), &key);
  944. } else {
  945. lResult = RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"), &key);
  946. }
  947. if ((lResult == ERROR_SUCCESS) && key) {
  948. dataSize = 0;
  949. lResult = RegQueryValueEx (key, FolderStr, NULL, &dataType, NULL, &dataSize);
  950. if ((lResult == ERROR_SUCCESS) &&
  951. ((dataType == REG_SZ) || (dataType == REG_EXPAND_SZ))
  952. ) {
  953. data = (PTSTR)LocalAlloc (LPTR, dataSize);
  954. if (data) {
  955. lResult = RegQueryValueEx (key, FolderStr, NULL, &dataType, (LPBYTE)data, &dataSize);
  956. if (lResult == ERROR_SUCCESS) {
  957. expDataSize = ExpandEnvironmentStrings (data, NULL, 0);
  958. if (expDataSize) {
  959. expData = (PTSTR)LocalAlloc (LPTR, (expDataSize + 1) * sizeof (TCHAR));
  960. expDataSize = ExpandEnvironmentStrings (data, expData, expDataSize);
  961. if (!expDataSize) {
  962. LocalFree (expData);
  963. expData = NULL;
  964. }
  965. }
  966. if (expDataSize) {
  967. result = expData;
  968. LocalFree (data);
  969. } else {
  970. result = data;
  971. }
  972. } else {
  973. LocalFree (data);
  974. }
  975. }
  976. }
  977. CloseHandle (key);
  978. }
  979. }
  980. if (result && !(*result)) {
  981. LocalFree (result);
  982. result = NULL;
  983. }
  984. return (PTSTR) result;
  985. }
  986. PTSTR
  987. GetShellFolderPath (
  988. IN INT Folder,
  989. IN PCTSTR FolderStr,
  990. IN BOOL UserFolder,
  991. OUT LPITEMIDLIST *pidl //OPTIONAL
  992. )
  993. {
  994. PTSTR result = NULL;
  995. HRESULT hResult;
  996. BOOL b;
  997. LPITEMIDLIST localpidl = NULL;
  998. IMalloc *mallocFn;
  999. if (pidl) {
  1000. *pidl = NULL;
  1001. }
  1002. hResult = SHGetMalloc (&mallocFn);
  1003. if (hResult != S_OK) {
  1004. return NULL;
  1005. }
  1006. hResult = SHGetSpecialFolderLocation (NULL, Folder, &localpidl);
  1007. if (hResult == S_OK) {
  1008. result = (PTSTR) LocalAlloc (LPTR, MAX_PATH);
  1009. if (result) {
  1010. b = SHGetPathFromIDList (localpidl, result);
  1011. if (b) {
  1012. if (pidl) {
  1013. *pidl = localpidl;
  1014. }
  1015. return result;
  1016. }
  1017. LocalFree (result);
  1018. result = NULL;
  1019. }
  1020. }
  1021. if (FolderStr) {
  1022. result = pFindSfPath (FolderStr, UserFolder);
  1023. }
  1024. mallocFn->Free (localpidl);
  1025. localpidl = NULL;
  1026. return result;
  1027. }
  1028. typedef HRESULT (WINAPI SHBINDTOPARENT)(LPCITEMIDLIST pidl, REFIID riid, VOID **ppv, LPCITEMIDLIST *ppidlLast);
  1029. typedef SHBINDTOPARENT *PSHBINDTOPARENT;
  1030. HRESULT
  1031. OurSHBindToParent (
  1032. IN LPCITEMIDLIST pidl,
  1033. IN REFIID riid,
  1034. OUT VOID **ppv,
  1035. OUT LPCITEMIDLIST *ppidlLast
  1036. )
  1037. {
  1038. HRESULT hr = E_FAIL;
  1039. HMODULE lib;
  1040. PSHBINDTOPARENT shBindToParent = NULL;
  1041. lib = LoadLibrary (TEXT("shell32.dll"));
  1042. if (lib) {
  1043. shBindToParent = (PSHBINDTOPARENT)GetProcAddress (lib, "SHBindToParent");
  1044. if (shBindToParent) {
  1045. hr = shBindToParent (pidl, riid, ppv, ppidlLast);
  1046. }
  1047. }
  1048. return hr;
  1049. }
  1050. //////////////////////////////////////////////////////////////////////////////////////
  1051. // if pctszPath corresponds to the path of one of the CSIDL_XXXX entries, then return
  1052. // its "pretty name", else return the standard path name
  1053. HRESULT _GetPrettyFolderName (HINSTANCE Instance, BOOL fNT4, LPCTSTR pctszPath, LPTSTR ptszName, UINT cchName)
  1054. {
  1055. UINT itemsIndex = 0;
  1056. PCSIDL_STRUCT items[2] = {g_UserShellFolders, g_CommonShellFolders};
  1057. PCSIDL_STRUCT p;
  1058. IMalloc *mallocFn;
  1059. LPITEMIDLIST pidl = NULL;
  1060. LPCITEMIDLIST pidlLast = NULL;
  1061. IShellFolder* psf = NULL;
  1062. HRESULT hr = S_OK;
  1063. PTSTR szPath = NULL;
  1064. PTSTR szAltPath = NULL;
  1065. STRRET strret;
  1066. TCHAR szDisplay1[2048];
  1067. TCHAR szDisplay2[2048];
  1068. BOOL checkAlternate = FALSE;
  1069. BOOL found = FALSE;
  1070. // First, we look to find the corresponding CSIDL if we can
  1071. // If we can't we will just copy the IN path to the OUT path.
  1072. for (itemsIndex = 0; itemsIndex < 2; itemsIndex ++) {
  1073. p = items [itemsIndex];
  1074. while (!found && (p->DirId >= 0)) {
  1075. szDisplay1 [0] = 0;
  1076. szDisplay2 [0] = 0;
  1077. pidl = NULL;
  1078. pidlLast = NULL;
  1079. szPath = NULL;
  1080. psf = NULL;
  1081. szPath = GetShellFolderPath (p->DirId, p->DirStr, p->DirUser, &pidl);
  1082. if (szPath && (0 == StrCmpI(pctszPath, szPath))) {
  1083. found = TRUE;
  1084. if (pidl) {
  1085. hr = OurSHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
  1086. if (SUCCEEDED(hr) && psf && pidlLast) {
  1087. hr = psf->GetDisplayNameOf (pidlLast, SHGDN_NORMAL, &strret);
  1088. if (SUCCEEDED (hr)) {
  1089. hr = _StrRetToBuf (&strret, pidlLast, szDisplay1, ARRAYSIZE(szDisplay1));
  1090. if (!SUCCEEDED (hr) || (0 == StrCmpI (szDisplay1, pctszPath))) {
  1091. // Failed or we just got back the complete folder spec. We don't need that!
  1092. szDisplay1 [0] = 0;
  1093. }
  1094. }
  1095. }
  1096. if (psf) {
  1097. psf->Release ();
  1098. psf = NULL;
  1099. }
  1100. }
  1101. }
  1102. if (pidl) {
  1103. hr = SHGetMalloc (&mallocFn);
  1104. if (SUCCEEDED (hr)) {
  1105. mallocFn->Free (pidl);
  1106. pidl = NULL;
  1107. }
  1108. }
  1109. if (szPath) {
  1110. LocalFree (szPath);
  1111. szPath = NULL;
  1112. }
  1113. if (szDisplay1 [0] && (p->AltDirId >= 0)) {
  1114. szPath = GetShellFolderPath (p->AltDirId, NULL, TRUE, &pidl);
  1115. if (pidl && szPath) {
  1116. hr = OurSHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
  1117. if (SUCCEEDED(hr) && psf && pidlLast) {
  1118. hr = psf->GetDisplayNameOf (pidlLast, SHGDN_INFOLDER, &strret);
  1119. if (SUCCEEDED (hr)) {
  1120. hr = _StrRetToBuf (&strret, pidlLast, szDisplay2, ARRAYSIZE(szDisplay2));
  1121. if (!SUCCEEDED (hr)) {
  1122. szDisplay2 [0] = 0;
  1123. }
  1124. }
  1125. }
  1126. if (psf) {
  1127. psf->Release ();
  1128. psf = NULL;
  1129. }
  1130. }
  1131. if (pidl) {
  1132. hr = SHGetMalloc (&mallocFn);
  1133. if (SUCCEEDED (hr)) {
  1134. mallocFn->Free (pidl);
  1135. pidl = NULL;
  1136. }
  1137. }
  1138. if (szPath) {
  1139. LocalFree (szPath);
  1140. szPath = NULL;
  1141. }
  1142. }
  1143. if (found) {
  1144. if ((!szDisplay1 [0]) || (0 == StrCmpI (szDisplay1, szDisplay2))) {
  1145. // we need to use the resource ID
  1146. if (!LoadString (Instance, p->DirResId, ptszName, cchName)) {
  1147. StrCpyN (ptszName, pctszPath, cchName);
  1148. }
  1149. } else {
  1150. StrCpyN (ptszName, szDisplay1, cchName);
  1151. }
  1152. break;
  1153. }
  1154. p ++;
  1155. }
  1156. if (found) {
  1157. break;
  1158. }
  1159. }
  1160. if (!found) {
  1161. StrCpyN (ptszName, pctszPath, cchName);
  1162. }
  1163. return S_OK;
  1164. }
  1165. //////////////////////////////////////////////////////////////////////////////////////
  1166. VOID _PopulateTree (HWND hwndTree, HTREEITEM hti, LPTSTR ptsz, UINT cch,
  1167. HRESULT (*fct)(HINSTANCE, BOOL, LPCTSTR, LPTSTR, UINT cchName),
  1168. DWORD dwFlags, HINSTANCE Instance, BOOL fNT4)
  1169. {
  1170. if (hwndTree && hti && ptsz)
  1171. {
  1172. // ISSUE: resolve flickering, this doesn't fix it
  1173. EnableWindow (hwndTree, FALSE);
  1174. TCHAR szDisplay[2048];
  1175. TCHAR szClean[2048];
  1176. TCHAR* ptszPtr = ptsz;
  1177. TCHAR* ptszParam = NULL;
  1178. while (*ptsz && (ptszPtr < (ptsz + cch)))
  1179. {
  1180. szDisplay[0] = 0;
  1181. BOOL fOK = TRUE;
  1182. LV_DATASTRUCT* plvds = (LV_DATASTRUCT*)LocalAlloc(LPTR, sizeof(LV_DATASTRUCT));
  1183. if (plvds)
  1184. {
  1185. plvds->fOverwrite = FALSE;
  1186. StrCpyN(szClean, ptszPtr, ARRAYSIZE(szClean));
  1187. LPITEMIDLIST pidl = NULL;
  1188. // if this is a filetype, restore the "*." before it, add pretty name
  1189. if (dwFlags == POPULATETREE_FLAGS_FILETYPES)
  1190. {
  1191. TCHAR szPretty[2048];
  1192. if (FAILED(_GetPrettyTypeName(szClean, szPretty, ARRAYSIZE(szPretty))))
  1193. {
  1194. szPretty[0] = 0;
  1195. }
  1196. memmove(szClean + 2, szClean, sizeof(szClean) - (2 * sizeof(TCHAR)));
  1197. *szClean = TEXT('*');
  1198. *(szClean + 1) = TEXT('.');
  1199. if (szPretty[0])
  1200. {
  1201. lstrcpy(szClean + lstrlen(szClean), TEXT(" - "));
  1202. lstrcpy(szClean + lstrlen(szClean), szPretty);
  1203. }
  1204. }
  1205. if (fOK)
  1206. {
  1207. if (szDisplay[0]) // if we already have a display name, use that and store the clean name
  1208. {
  1209. plvds->pszPureName = StrDup(szClean);
  1210. }
  1211. else
  1212. {
  1213. if (fct) // if there's a pretty-fying function, use it
  1214. {
  1215. fct(Instance, fNT4, szClean, szDisplay, ARRAYSIZE(szDisplay));
  1216. plvds->pszPureName = StrDup(szClean);
  1217. }
  1218. else if (POPULATETREE_FLAGS_FILETYPES) // ISSUE: this is hacky, clean this up
  1219. {
  1220. StrCpyN(szDisplay, szClean, ARRAYSIZE(szDisplay));
  1221. plvds->pszPureName = StrDup(ptsz);
  1222. }
  1223. else
  1224. {
  1225. StrCpyN(szDisplay, szClean, ARRAYSIZE(szDisplay));
  1226. }
  1227. }
  1228. TV_INSERTSTRUCT tis = {0};
  1229. tis.hParent = hti;
  1230. tis.hInsertAfter = TVI_SORT;
  1231. tis.item.mask = TVIF_TEXT | TVIF_PARAM;
  1232. tis.item.lParam = (LPARAM)plvds;
  1233. tis.item.pszText = szDisplay;
  1234. TreeView_InsertItem(hwndTree, &tis);
  1235. }
  1236. ptszPtr += (1 + lstrlen(ptszPtr));
  1237. }
  1238. }
  1239. EnableWindow (hwndTree, TRUE);
  1240. }
  1241. }
  1242. //////////////////////////////////////////////////////////////////////////////////////
  1243. UINT _ListView_InsertItem(HWND hwndList, LPTSTR ptsz)
  1244. {
  1245. LVITEM lvitem = {0};
  1246. lvitem.mask = LVIF_TEXT;
  1247. lvitem.iItem = ListView_GetItemCount(hwndList);
  1248. lvitem.pszText = ptsz;
  1249. return ListView_InsertItem(hwndList, &lvitem);
  1250. }
  1251. //////////////////////////////////////////////////////////////////////////////////////
  1252. HRESULT _GetPrettyTypeName(LPCTSTR pctszType, LPTSTR ptszPrettyType, UINT cchPrettyType)
  1253. {
  1254. HRESULT hr = E_FAIL;
  1255. BOOL found = FALSE;
  1256. TCHAR tszTypeName[MAX_PATH];
  1257. LPTSTR ptszType;
  1258. TCHAR szTypeName[MAX_PATH];
  1259. DWORD cchTypeName = MAX_PATH;
  1260. TCHAR szCmdLine[MAX_PATH];
  1261. DWORD cchCmdLine = MAX_PATH;
  1262. DWORD dwType = REG_SZ;
  1263. if (TEXT('*') == pctszType[0] && TEXT('.') == pctszType[1])
  1264. {
  1265. ptszType = (LPTSTR)pctszType + 1;
  1266. }
  1267. else
  1268. {
  1269. tszTypeName[0] = TEXT('.');
  1270. lstrcpy(tszTypeName + 1, pctszType);
  1271. ptszType = tszTypeName;
  1272. }
  1273. // let's find the progId
  1274. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, ptszType, NULL, &dwType, szTypeName, &cchTypeName))
  1275. {
  1276. LONG result;
  1277. DWORD cchPrettyName = cchPrettyType;
  1278. PTSTR cmdPtr, resIdPtr;
  1279. INT resId;
  1280. HMODULE dllModule;
  1281. // let's see if this progId has the FriendlyTypeName value name
  1282. if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, szTypeName, TEXT("FriendlyTypeName"), &dwType, szCmdLine, &cchCmdLine)) {
  1283. cmdPtr = szCmdLine;
  1284. if (_tcsnextc (cmdPtr) == TEXT('@')) {
  1285. cmdPtr = _tcsinc (cmdPtr);
  1286. }
  1287. if (cmdPtr) {
  1288. resIdPtr = _tcsrchr (cmdPtr, TEXT(','));
  1289. if (resIdPtr) {
  1290. *resIdPtr = 0;
  1291. resIdPtr ++;
  1292. }
  1293. }
  1294. if (cmdPtr && resIdPtr) {
  1295. resId = _ttoi (resIdPtr);
  1296. if (resId < 0) {
  1297. // let's load the resource string from that PE file
  1298. // use resIdPtr to access the string resource
  1299. dllModule = LoadLibraryEx (cmdPtr, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1300. if (dllModule) {
  1301. found = (LoadString (dllModule, (UINT)(-resId), ptszPrettyType, cchPrettyName) > 0);
  1302. hr = S_OK;
  1303. FreeLibrary (dllModule);
  1304. }
  1305. }
  1306. }
  1307. }
  1308. if ((!found) && (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, szTypeName, NULL, &dwType, ptszPrettyType, &cchPrettyName)))
  1309. {
  1310. hr = S_OK;
  1311. }
  1312. }
  1313. return hr;
  1314. }
  1315. //////////////////////////////////////////////////////////////////////////////////////
  1316. BOOL _DriveIdIsFloppyNT(int iDrive)
  1317. {
  1318. BOOL fRetVal = FALSE;
  1319. HANDLE hDevice;
  1320. UINT i;
  1321. TCHAR szTemp[] = TEXT("\\\\.\\a:");
  1322. if (iDrive >= 0 && iDrive < 26)
  1323. {
  1324. szTemp[4] += (TCHAR)iDrive;
  1325. hDevice = CreateFile(szTemp, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
  1326. NULL, OPEN_EXISTING, 0, NULL);
  1327. if (INVALID_HANDLE_VALUE != hDevice)
  1328. {
  1329. DISK_GEOMETRY rgGeometry[15];
  1330. DWORD cbIn = sizeof(rgGeometry);
  1331. DWORD cbReturned;
  1332. if (DeviceIoControl(hDevice, IOCTL_DISK_GET_MEDIA_TYPES,
  1333. NULL, 0, rgGeometry, cbIn, &cbReturned, NULL))
  1334. {
  1335. UINT cStructReturned = cbReturned / sizeof(DISK_GEOMETRY);
  1336. for (i = 0; i < cStructReturned; i++)
  1337. {
  1338. switch (rgGeometry[i].MediaType)
  1339. {
  1340. case F5_1Pt2_512:
  1341. case F3_1Pt44_512:
  1342. case F3_2Pt88_512:
  1343. case F3_20Pt8_512:
  1344. case F3_720_512:
  1345. case F5_360_512:
  1346. case F5_320_512:
  1347. case F5_320_1024:
  1348. case F5_180_512:
  1349. case F5_160_512:
  1350. fRetVal = TRUE;
  1351. break;
  1352. case Unknown:
  1353. case RemovableMedia:
  1354. case FixedMedia:
  1355. default:
  1356. break;
  1357. }
  1358. }
  1359. }
  1360. CloseHandle (hDevice);
  1361. }
  1362. }
  1363. return fRetVal;
  1364. }
  1365. ///////////////////////////////////////////
  1366. #define DEVPB_DEVTYP_525_0360 0
  1367. #define DEVPB_DEVTYP_525_1200 1
  1368. #define DEVPB_DEVTYP_350_0720 2
  1369. #define DEVPB_DEVTYP_350_1440 7
  1370. #define DEVPB_DEVTYP_350_2880 9
  1371. #define DEVPB_DEVTYP_FIXED 5
  1372. #define DEVPB_DEVTYP_NECHACK 4 // for 3rd FE floppy
  1373. #define DEVPB_DEVTYP_350_120M 6
  1374. #define CARRY_FLAG 0x01
  1375. #define VWIN32_DIOC_DOS_IOCTL 1
  1376. // DIOCRegs
  1377. // Structure with i386 registers for making DOS_IOCTLS
  1378. // vwin32 DIOC handler interprets lpvInBuffer , lpvOutBuffer to be this struc.
  1379. // and does the int 21
  1380. // reg_flags is valid only for lpvOutBuffer->reg_Flags
  1381. typedef struct DIOCRegs {
  1382. DWORD reg_EBX;
  1383. DWORD reg_EDX;
  1384. DWORD reg_ECX;
  1385. DWORD reg_EAX;
  1386. DWORD reg_EDI;
  1387. DWORD reg_ESI;
  1388. DWORD reg_Flags;
  1389. } DIOC_REGISTERS;
  1390. #pragma pack(1)
  1391. typedef struct _DOSDPB {
  1392. BYTE specialFunc; //
  1393. BYTE devType; //
  1394. WORD devAttr; //
  1395. WORD cCyl; // number of cylinders
  1396. BYTE mediaType; //
  1397. WORD cbSec; // Bytes per sector
  1398. BYTE secPerClus; // Sectors per cluster
  1399. WORD cSecRes; // Reserved sectors
  1400. BYTE cFAT; // FATs
  1401. WORD cDir; // Root Directory Entries
  1402. WORD cSec; // Total number of sectors in image
  1403. BYTE bMedia; // Media descriptor
  1404. WORD secPerFAT; // Sectors per FAT
  1405. WORD secPerTrack; // Sectors per track
  1406. WORD cHead; // Heads
  1407. DWORD cSecHidden; // Hidden sectors
  1408. DWORD cTotalSectors; // Total sectors, if cbSec is zero
  1409. BYTE reserved[6]; //
  1410. } DOSDPB, *PDOSDPB;
  1411. #pragma pack()
  1412. BOOL _DriveIOCTL(int iDrive, int cmd, void *pvIn, DWORD dwIn, void *pvOut, DWORD dwOut, BOOL fFileSystem = FALSE,
  1413. HANDLE handle = INVALID_HANDLE_VALUE)
  1414. {
  1415. BOOL fHandlePassedIn = TRUE;
  1416. BOOL fSuccess = FALSE;
  1417. DWORD dwRead;
  1418. if (INVALID_HANDLE_VALUE == handle)
  1419. {
  1420. handle = CreateFileA("\\\\.\\VWIN32", 0, 0, 0, 0,
  1421. FILE_FLAG_DELETE_ON_CLOSE, 0);
  1422. fHandlePassedIn = FALSE;
  1423. }
  1424. if (INVALID_HANDLE_VALUE != handle)
  1425. {
  1426. DIOC_REGISTERS reg;
  1427. //
  1428. // On non-NT, we talk to VWIN32, issuing reads (which are converted
  1429. // internally to DEVIOCTLs)
  1430. //
  1431. // this is a real hack (talking to VWIN32) on NT we can just
  1432. // open the device, we dont have to go through VWIN32
  1433. //
  1434. reg.reg_EBX = (DWORD)iDrive + 1; // make 1 based drive number
  1435. reg.reg_EDX = (DWORD)(ULONG_PTR)pvOut; // out buffer
  1436. reg.reg_ECX = cmd; // device specific command code
  1437. reg.reg_EAX = 0x440D; // generic read ioctl
  1438. reg.reg_Flags = 0x0001; // flags, assume error (carry)
  1439. DeviceIoControl(handle, VWIN32_DIOC_DOS_IOCTL, &reg, sizeof(reg), &reg, sizeof(reg), &dwRead, NULL);
  1440. fSuccess = !(reg.reg_Flags & 0x0001);
  1441. if (!fHandlePassedIn)
  1442. CloseHandle(handle);
  1443. }
  1444. return fSuccess;
  1445. }
  1446. BOOL _DriveIdIsFloppy9X(int iDrive)
  1447. {
  1448. DOSDPB SupportedGeometry; // s/b big enough for all
  1449. BOOL fRet = FALSE;
  1450. SupportedGeometry.specialFunc = 0;
  1451. if (_DriveIOCTL(iDrive, 0x860, NULL, 0, &SupportedGeometry, sizeof(SupportedGeometry)))
  1452. {
  1453. switch( SupportedGeometry.devType )
  1454. {
  1455. case DEVPB_DEVTYP_525_0360:
  1456. case DEVPB_DEVTYP_525_1200:
  1457. case DEVPB_DEVTYP_350_0720:
  1458. case DEVPB_DEVTYP_350_1440:
  1459. case DEVPB_DEVTYP_350_2880:
  1460. fRet = TRUE;
  1461. break;
  1462. case DEVPB_DEVTYP_FIXED:
  1463. case DEVPB_DEVTYP_NECHACK: // for 3rd FE floppy
  1464. case DEVPB_DEVTYP_350_120M:
  1465. fRet = FALSE;
  1466. break;
  1467. }
  1468. }
  1469. return fRet;
  1470. }
  1471. ///////////////////////////////////////////
  1472. BOOL _DriveIdIsFloppy(BOOL fIsNT, int iDrive)
  1473. {
  1474. if (fIsNT)
  1475. {
  1476. return _DriveIdIsFloppyNT(iDrive);
  1477. }
  1478. else
  1479. {
  1480. return _DriveIdIsFloppy9X(iDrive);
  1481. }
  1482. }
  1483. ///////////////////////////////////////////
  1484. BOOL _DriveStrIsFloppy(BOOL fIsNT, PCTSTR pszPath)
  1485. {
  1486. int iDrive;
  1487. iDrive = towlower(pszPath[0]) - TEXT('a');
  1488. return _DriveIdIsFloppy(fIsNT, iDrive);
  1489. }
  1490. ///////////////////////////////////////////
  1491. INT _GetFloppyNumber(BOOL fIsNT)
  1492. {
  1493. static int iFloppy = -1;
  1494. static bool fInit = FALSE;
  1495. if (!fInit)
  1496. {
  1497. DWORD dwLog = GetLogicalDrives();
  1498. for (int i = 0; i < 26; i++)
  1499. {
  1500. if( !((dwLog >> i) & 0x01) || !_DriveIdIsFloppy(fIsNT, i) )
  1501. {
  1502. break;
  1503. }
  1504. else
  1505. {
  1506. iFloppy = i;
  1507. }
  1508. }
  1509. fInit = TRUE;
  1510. }
  1511. return iFloppy;
  1512. }
  1513. ////////////////////////////////////////////////////////
  1514. /*
  1515. * StrCmpN - Compare n bytes
  1516. *
  1517. * returns See lstrcmp return values.
  1518. */
  1519. #ifdef BIG_ENDIAN
  1520. #define READNATIVEWORD(x) MAKEWORD(*(char*)(x), *(char*)((char*)(x) + 1))
  1521. #else
  1522. #define READNATIVEWORD(x) MAKEWORD(*(char*)((char*)(x) + 1), *(char*)(x))
  1523. #endif
  1524. /*
  1525. * ChrCmp - Case sensitive character comparison for DBCS
  1526. * Assumes w1, wMatch are characters to be compared
  1527. * Return FALSE if they match, TRUE if no match
  1528. */
  1529. __inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch)
  1530. {
  1531. /* Most of the time this won't match, so test it first for speed.
  1532. */
  1533. if (LOBYTE(w1) == LOBYTE(wMatch))
  1534. {
  1535. if (IsDBCSLeadByte(LOBYTE(w1)))
  1536. {
  1537. return(w1 != wMatch);
  1538. }
  1539. return FALSE;
  1540. }
  1541. return TRUE;
  1542. }
  1543. BOOL _SetTextLoadString(HINSTANCE hInst, HWND hwnd, UINT idText)
  1544. {
  1545. TCHAR sz[MAX_LOADSTRING];
  1546. if (LoadString(hInst, idText, sz, ARRAYSIZE(sz)))
  1547. {
  1548. SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)sz);
  1549. return TRUE;
  1550. }
  1551. else
  1552. {
  1553. return FALSE;
  1554. }
  1555. }
  1556. typedef HANDLE (WINAPI CREATETOOLHELP32SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
  1557. typedef CREATETOOLHELP32SNAPSHOT *PCREATETOOLHELP32SNAPSHOT;
  1558. #ifdef UNICODE
  1559. typedef BOOL (WINAPI PROCESS32FIRST)(HANDLE hSnapshot, LPPROCESSENTRY32W lppe);
  1560. typedef BOOL (WINAPI PROCESS32NEXT)(HANDLE hSnapshot, LPPROCESSENTRY32W lppe);
  1561. #else
  1562. typedef BOOL (WINAPI PROCESS32FIRST)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
  1563. typedef BOOL (WINAPI PROCESS32NEXT)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
  1564. #endif
  1565. typedef PROCESS32FIRST *PPROCESS32FIRST;
  1566. typedef PROCESS32NEXT *PPROCESS32NEXT;
  1567. VOID
  1568. KillExplorer (
  1569. IN HINSTANCE Instance,
  1570. IN HWND hwndDlg,
  1571. IN PCTSTR Args
  1572. )
  1573. {
  1574. HANDLE h, h1;
  1575. PROCESSENTRY32 pe;
  1576. TCHAR szExplorerPath[MAX_PATH];
  1577. PCREATETOOLHELP32SNAPSHOT dynCreateToolhelp32Snapshot;
  1578. PPROCESS32FIRST dynProcess32First;
  1579. PPROCESS32NEXT dynProcess32Next;
  1580. HMODULE lib;
  1581. lib = LoadLibrary (TEXT("kernel32.dll"));
  1582. if (!lib) {
  1583. return;
  1584. }
  1585. dynCreateToolhelp32Snapshot = (PCREATETOOLHELP32SNAPSHOT) GetProcAddress (lib, "CreateToolhelp32Snapshot");
  1586. #ifdef UNICODE
  1587. dynProcess32First = (PPROCESS32FIRST) GetProcAddress (lib, "Process32FirstW");
  1588. dynProcess32Next = (PPROCESS32NEXT) GetProcAddress (lib, "Process32NextW");
  1589. #else
  1590. dynProcess32First = (PPROCESS32FIRST) GetProcAddress (lib, "Process32First");
  1591. dynProcess32Next = (PPROCESS32NEXT) GetProcAddress (lib, "Process32Next");
  1592. #endif
  1593. __try {
  1594. if (!dynCreateToolhelp32Snapshot || !dynProcess32Next || !dynProcess32First) {
  1595. __leave;
  1596. }
  1597. h = dynCreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
  1598. if (h == INVALID_HANDLE_VALUE) {
  1599. __leave;
  1600. }
  1601. GetWindowsDirectory (szExplorerPath, MAX_PATH);
  1602. PathAppend (szExplorerPath, TEXT("explorer.exe"));
  1603. pe.dwSize = sizeof (PROCESSENTRY32);
  1604. if (dynProcess32First (h, &pe)) {
  1605. do {
  1606. if (!StrCmpI (pe.szExeFile, TEXT("explorer.exe")) ||
  1607. !StrCmpI (pe.szExeFile, szExplorerPath)
  1608. ) {
  1609. h1 = OpenProcess (PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
  1610. if (h1) {
  1611. g_Explorer = StrDup (szExplorerPath);
  1612. TerminateProcess (h1, 1);
  1613. CloseHandle (h1);
  1614. break;
  1615. }
  1616. }
  1617. } while (dynProcess32Next (h, &pe));
  1618. }
  1619. CloseHandle (h);
  1620. }
  1621. __finally {
  1622. FreeLibrary (lib);
  1623. }
  1624. }
  1625. typedef enum {
  1626. MS_MAX_PATH,
  1627. MS_NO_ARG,
  1628. MS_BOOL,
  1629. MS_INT,
  1630. MS_RECT,
  1631. MS_BLOB
  1632. } METRICSTYLE;
  1633. VOID
  1634. __RefreshMetric (
  1635. IN METRICSTYLE msStyle,
  1636. IN UINT uGetMetricId,
  1637. IN UINT uSetMetricId,
  1638. IN UINT uBlobSize
  1639. )
  1640. {
  1641. BYTE byBuffer[MAX_PATH * 4];
  1642. PVOID blob;
  1643. switch (msStyle) {
  1644. case MS_NO_ARG:
  1645. SystemParametersInfo (uSetMetricId, 0, NULL, SPIF_SENDCHANGE);
  1646. break;
  1647. case MS_BLOB:
  1648. blob = LocalAlloc (LPTR, uBlobSize);
  1649. if (blob) {
  1650. if (SystemParametersInfo (uGetMetricId, uBlobSize, blob, SPIF_UPDATEINIFILE)) {
  1651. SystemParametersInfo (uSetMetricId, 0, blob, SPIF_SENDCHANGE);
  1652. }
  1653. LocalFree (blob);
  1654. }
  1655. break;
  1656. case MS_RECT:
  1657. if (SystemParametersInfo (uGetMetricId, 0, byBuffer, SPIF_UPDATEINIFILE)) {
  1658. SystemParametersInfo (uSetMetricId, 0, byBuffer, SPIF_SENDCHANGE);
  1659. }
  1660. break;
  1661. case MS_BOOL:
  1662. if (SystemParametersInfo (uGetMetricId, 0, byBuffer, SPIF_UPDATEINIFILE)) {
  1663. SystemParametersInfo (uSetMetricId, *((BOOL *) byBuffer), NULL, SPIF_SENDCHANGE);
  1664. }
  1665. break;
  1666. case MS_INT:
  1667. if (SystemParametersInfo (uGetMetricId, 0, byBuffer, SPIF_UPDATEINIFILE)) {
  1668. SystemParametersInfo (uSetMetricId, *((UINT *) byBuffer), NULL, SPIF_SENDCHANGE);
  1669. }
  1670. break;
  1671. case MS_MAX_PATH:
  1672. if (SystemParametersInfo (uGetMetricId, MAX_PATH, byBuffer, SPIF_UPDATEINIFILE)) {
  1673. SystemParametersInfo (uSetMetricId, 0, byBuffer, SPIF_SENDCHANGE);
  1674. }
  1675. break;
  1676. }
  1677. return;
  1678. }
  1679. VOID
  1680. SwitchToClassicDesktop (
  1681. IN HINSTANCE Instance,
  1682. IN HWND hwndDlg,
  1683. IN PCTSTR Args
  1684. )
  1685. {
  1686. LONG result;
  1687. HKEY key = NULL;
  1688. TCHAR data[] = TEXT("0");
  1689. //
  1690. // The only thing that we need to do is to turn off:
  1691. // HKCU\Software\Microsoft\Windows\CurrentVersion\ThemeManager [ThemeActive]
  1692. //
  1693. result = RegOpenKeyEx (
  1694. HKEY_CURRENT_USER,
  1695. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"),
  1696. 0,
  1697. KEY_WRITE,
  1698. &key
  1699. );
  1700. if ((result == ERROR_SUCCESS) &&
  1701. (key)
  1702. ) {
  1703. result = RegSetValueEx (
  1704. key,
  1705. TEXT("ThemeActive"),
  1706. 0,
  1707. REG_SZ,
  1708. (PBYTE)data,
  1709. sizeof (data)
  1710. );
  1711. RegCloseKey (key);
  1712. }
  1713. }
  1714. typedef struct
  1715. {
  1716. UINT cbSize;
  1717. SHELLSTATE ss;
  1718. } REGSHELLSTATE, *PREGSHELLSTATE;
  1719. VOID
  1720. SwitchToClassicTaskBar (
  1721. IN HINSTANCE Instance,
  1722. IN HWND hwndDlg,
  1723. IN PCTSTR Args
  1724. )
  1725. {
  1726. HKEY key = NULL;
  1727. DWORD dataType;
  1728. DWORD dataSize = 0;
  1729. PBYTE data = NULL;
  1730. PREGSHELLSTATE shellState = NULL;
  1731. LONG result;
  1732. //
  1733. // The only thing that we need to do is to turn off the fStartPanelOn field in:
  1734. // HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [ShellState]
  1735. //
  1736. result = RegOpenKeyEx (
  1737. HKEY_CURRENT_USER,
  1738. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  1739. 0,
  1740. KEY_READ | KEY_WRITE,
  1741. &key
  1742. );
  1743. if ((result == ERROR_SUCCESS) &&
  1744. (key)
  1745. ) {
  1746. result = RegQueryValueEx (
  1747. key,
  1748. TEXT ("ShellState"),
  1749. NULL,
  1750. &dataType,
  1751. NULL,
  1752. &dataSize
  1753. );
  1754. if ((result == ERROR_SUCCESS) || (result == ERROR_MORE_DATA)) {
  1755. data = (PBYTE) LocalAlloc (LPTR, dataSize);
  1756. if (data) {
  1757. result = RegQueryValueEx (
  1758. key,
  1759. TEXT ("ShellState"),
  1760. NULL,
  1761. &dataType,
  1762. data,
  1763. &dataSize
  1764. );
  1765. if ((result == ERROR_SUCCESS) &&
  1766. (dataType == REG_BINARY) &&
  1767. (dataSize == sizeof (REGSHELLSTATE))
  1768. ) {
  1769. if (dataType == REG_BINARY) {
  1770. shellState = (PREGSHELLSTATE) data;
  1771. shellState->ss.fStartPanelOn = FALSE;
  1772. RegSetValueEx (
  1773. key,
  1774. TEXT("ShellState"),
  1775. 0,
  1776. REG_BINARY,
  1777. (PBYTE)data,
  1778. dataSize
  1779. );
  1780. }
  1781. }
  1782. LocalFree (data);
  1783. }
  1784. }
  1785. RegCloseKey (key);
  1786. }
  1787. }
  1788. VOID
  1789. RegisterFonts (
  1790. IN HINSTANCE Instance,
  1791. IN HWND hwndDlg,
  1792. IN PCTSTR Args
  1793. )
  1794. {
  1795. WIN32_FIND_DATA findData;
  1796. HANDLE findHandle = INVALID_HANDLE_VALUE;
  1797. PTSTR fontDir = NULL;
  1798. TCHAR fontPattern [MAX_PATH];
  1799. //
  1800. // Let's (re)register all the fonts (in case the user migrated some new ones).
  1801. //
  1802. fontDir = GetShellFolderPath (CSIDL_FONTS, NULL, TRUE, NULL);
  1803. if (fontDir) {
  1804. StrCpyN (fontPattern, fontDir, ARRAYSIZE (fontPattern) - 4);
  1805. StrCat (fontPattern, TEXT("\\*.*"));
  1806. findHandle = FindFirstFile (fontPattern, &findData);
  1807. if (findHandle != INVALID_HANDLE_VALUE) {
  1808. do {
  1809. AddFontResource (findData.cFileName);
  1810. } while (FindNextFile (findHandle, &findData));
  1811. FindClose (findHandle);
  1812. }
  1813. }
  1814. }
  1815. VOID
  1816. RefreshMetrics (
  1817. IN HINSTANCE Instance,
  1818. IN HWND hwndDlg,
  1819. IN PCTSTR Args
  1820. )
  1821. {
  1822. //
  1823. // Refresh all system metrics
  1824. //
  1825. __RefreshMetric (MS_NO_ARG, 0, SPI_SETCURSORS, 0);
  1826. __RefreshMetric (MS_NO_ARG, 0, SPI_SETDESKPATTERN, 0);
  1827. __RefreshMetric (MS_MAX_PATH, SPI_GETDESKWALLPAPER, SPI_SETDESKWALLPAPER, 0);
  1828. __RefreshMetric (MS_BOOL, SPI_GETFONTSMOOTHING, SPI_SETFONTSMOOTHING, 0);
  1829. __RefreshMetric (MS_RECT, SPI_GETWORKAREA, SPI_SETWORKAREA, 0);
  1830. __RefreshMetric (MS_BLOB, SPI_GETICONMETRICS, SPI_SETICONMETRICS, sizeof (ICONMETRICS));
  1831. __RefreshMetric (MS_NO_ARG, 0, SPI_SETICONS, 0);
  1832. __RefreshMetric (MS_BLOB, SPI_GETICONTITLELOGFONT, SPI_SETICONTITLELOGFONT, sizeof (LOGFONT));
  1833. __RefreshMetric (MS_BOOL, SPI_GETICONTITLEWRAP, SPI_SETICONTITLEWRAP, 0);
  1834. __RefreshMetric (MS_BOOL, SPI_GETBEEP, SPI_SETBEEP, 0);
  1835. __RefreshMetric (MS_BOOL, SPI_GETKEYBOARDCUES, SPI_SETKEYBOARDCUES, 0);
  1836. __RefreshMetric (MS_INT, SPI_GETKEYBOARDDELAY, SPI_SETKEYBOARDDELAY, 0);
  1837. __RefreshMetric (MS_BOOL, SPI_GETKEYBOARDPREF, SPI_SETKEYBOARDPREF, 0);
  1838. __RefreshMetric (MS_INT, SPI_GETKEYBOARDSPEED, SPI_SETKEYBOARDSPEED, 0);
  1839. //__RefreshMetric (MS_BOOL, SPI_GETMOUSEBUTTONSWAP, SPI_SETMOUSEBUTTONSWAP, 0);
  1840. __RefreshMetric (MS_INT, SPI_GETMOUSEHOVERHEIGHT, SPI_SETMOUSEHOVERHEIGHT, 0);
  1841. __RefreshMetric (MS_INT, SPI_GETMOUSEHOVERTIME, SPI_SETMOUSEHOVERTIME, 0);
  1842. __RefreshMetric (MS_INT, SPI_GETMOUSEHOVERWIDTH, SPI_SETMOUSEHOVERWIDTH, 0);
  1843. __RefreshMetric (MS_INT, SPI_GETMOUSESPEED, SPI_SETMOUSESPEED, 0);
  1844. __RefreshMetric (MS_INT, SPI_GETMOUSETRAILS, SPI_SETMOUSETRAILS, 0);
  1845. //__RefreshMetric (MS_INT, SPI_GETDOUBLECLICKTIME, SPI_SETDOUBLECLICKTIME, 0);
  1846. //__RefreshMetric (MS_INT, SPI_GETDOUBLECLKHEIGHT, SPI_SETDOUBLECLKHEIGHT, 0);
  1847. //__RefreshMetric (MS_INT, SPI_GETDOUBLECLKWIDTH, SPI_SETDOUBLECLKWIDTH, 0);
  1848. __RefreshMetric (MS_BOOL, SPI_GETSNAPTODEFBUTTON, SPI_SETSNAPTODEFBUTTON, 0);
  1849. __RefreshMetric (MS_INT, SPI_GETWHEELSCROLLLINES, SPI_SETWHEELSCROLLLINES, 0);
  1850. __RefreshMetric (MS_BOOL, SPI_GETMENUDROPALIGNMENT, SPI_SETMENUDROPALIGNMENT, 0);
  1851. __RefreshMetric (MS_BOOL, SPI_GETMENUFADE, SPI_SETMENUFADE, 0);
  1852. __RefreshMetric (MS_BOOL, SPI_GETMENUSHOWDELAY, SPI_SETMENUSHOWDELAY, 0);
  1853. __RefreshMetric (MS_BOOL, SPI_GETLOWPOWERACTIVE, SPI_SETLOWPOWERACTIVE, 0);
  1854. __RefreshMetric (MS_INT, SPI_GETLOWPOWERTIMEOUT, SPI_SETLOWPOWERTIMEOUT, 0);
  1855. __RefreshMetric (MS_BOOL, SPI_GETPOWEROFFACTIVE, SPI_SETPOWEROFFACTIVE, 0);
  1856. __RefreshMetric (MS_INT, SPI_GETPOWEROFFTIMEOUT, SPI_SETPOWEROFFTIMEOUT, 0);
  1857. __RefreshMetric (MS_BOOL, SPI_GETSCREENSAVEACTIVE, SPI_SETSCREENSAVEACTIVE, 0);
  1858. __RefreshMetric (MS_INT, SPI_GETSCREENSAVETIMEOUT, SPI_SETSCREENSAVETIMEOUT, 0);
  1859. __RefreshMetric (MS_BOOL, SPI_GETCOMBOBOXANIMATION, SPI_SETCOMBOBOXANIMATION, 0);
  1860. __RefreshMetric (MS_BOOL, SPI_GETCURSORSHADOW, SPI_SETCURSORSHADOW, 0);
  1861. __RefreshMetric (MS_BOOL, SPI_GETGRADIENTCAPTIONS, SPI_SETGRADIENTCAPTIONS, 0);
  1862. __RefreshMetric (MS_BOOL, SPI_GETHOTTRACKING, SPI_SETHOTTRACKING, 0);
  1863. __RefreshMetric (MS_BOOL, SPI_GETLISTBOXSMOOTHSCROLLING, SPI_SETLISTBOXSMOOTHSCROLLING, 0);
  1864. __RefreshMetric (MS_BOOL, SPI_GETSELECTIONFADE, SPI_SETSELECTIONFADE, 0);
  1865. __RefreshMetric (MS_BOOL, SPI_GETTOOLTIPANIMATION, SPI_SETTOOLTIPANIMATION, 0);
  1866. __RefreshMetric (MS_BOOL, SPI_GETTOOLTIPFADE, SPI_SETTOOLTIPFADE, 0);
  1867. __RefreshMetric (MS_BOOL, SPI_GETUIEFFECTS, SPI_SETUIEFFECTS, 0);
  1868. __RefreshMetric (MS_BOOL, SPI_GETACTIVEWINDOWTRACKING, SPI_SETACTIVEWINDOWTRACKING, 0);
  1869. __RefreshMetric (MS_BOOL, SPI_GETACTIVEWNDTRKZORDER, SPI_SETACTIVEWNDTRKZORDER, 0);
  1870. __RefreshMetric (MS_INT, SPI_GETACTIVEWNDTRKTIMEOUT, SPI_SETACTIVEWNDTRKTIMEOUT, 0);
  1871. __RefreshMetric (MS_BLOB, SPI_GETANIMATION, SPI_SETANIMATION, sizeof (ANIMATIONINFO));
  1872. __RefreshMetric (MS_INT, SPI_GETBORDER, SPI_SETBORDER, 0);
  1873. __RefreshMetric (MS_INT, SPI_GETCARETWIDTH, SPI_SETCARETWIDTH, 0);
  1874. __RefreshMetric (MS_BOOL, SPI_GETDRAGFULLWINDOWS, SPI_SETDRAGFULLWINDOWS, 0);
  1875. __RefreshMetric (MS_INT, SPI_GETFOREGROUNDFLASHCOUNT, SPI_SETFOREGROUNDFLASHCOUNT, 0);
  1876. __RefreshMetric (MS_INT, SPI_GETFOREGROUNDLOCKTIMEOUT, SPI_SETFOREGROUNDLOCKTIMEOUT, 0);
  1877. __RefreshMetric (MS_BLOB, SPI_GETMINIMIZEDMETRICS, SPI_SETMINIMIZEDMETRICS, sizeof (MINIMIZEDMETRICS));
  1878. __RefreshMetric (MS_BLOB, SPI_GETNONCLIENTMETRICS, SPI_SETNONCLIENTMETRICS, sizeof (NONCLIENTMETRICS));
  1879. __RefreshMetric (MS_BOOL, SPI_GETSHOWIMEUI, SPI_SETSHOWIMEUI, 0);
  1880. // SPI_SETMOUSE
  1881. // SPI_SETDRAGHEIGHT
  1882. // SPI_SETDRAGWIDTH
  1883. __RefreshMetric (MS_BLOB, SPI_GETACCESSTIMEOUT, SPI_SETACCESSTIMEOUT, sizeof (ACCESSTIMEOUT));
  1884. __RefreshMetric (MS_BLOB, SPI_GETFILTERKEYS, SPI_SETFILTERKEYS, sizeof (FILTERKEYS));
  1885. __RefreshMetric (MS_BLOB, SPI_GETHIGHCONTRAST, SPI_SETHIGHCONTRAST, sizeof (HIGHCONTRAST));
  1886. __RefreshMetric (MS_BLOB, SPI_GETMOUSEKEYS, SPI_SETMOUSEKEYS, sizeof (MOUSEKEYS));
  1887. __RefreshMetric (MS_BLOB, SPI_GETSERIALKEYS, SPI_SETSERIALKEYS, sizeof (SERIALKEYS));
  1888. __RefreshMetric (MS_BOOL, SPI_GETSHOWSOUNDS, SPI_SETSHOWSOUNDS, 0);
  1889. __RefreshMetric (MS_BLOB, SPI_GETSOUNDSENTRY, SPI_SETSOUNDSENTRY, sizeof (SOUNDSENTRY));
  1890. __RefreshMetric (MS_BLOB, SPI_GETSTICKYKEYS, SPI_SETSTICKYKEYS, sizeof (STICKYKEYS));
  1891. __RefreshMetric (MS_BLOB, SPI_GETTOGGLEKEYS, SPI_SETTOGGLEKEYS, sizeof (TOGGLEKEYS));
  1892. }
  1893. VOID
  1894. AskForLogOff (
  1895. IN HINSTANCE Instance,
  1896. IN HWND hwndDlg,
  1897. IN PCTSTR Args
  1898. )
  1899. {
  1900. g_LogOffSystem = TRUE;
  1901. }
  1902. VOID
  1903. AskForReboot (
  1904. IN HINSTANCE Instance,
  1905. IN HWND hwndDlg,
  1906. IN PCTSTR Args
  1907. )
  1908. {
  1909. g_RebootSystem = TRUE;
  1910. }
  1911. VOID
  1912. SaveOFStatus (
  1913. IN HINSTANCE Instance,
  1914. IN HWND hwndDlg,
  1915. IN PCTSTR Args
  1916. )
  1917. {
  1918. HKEY key = NULL;
  1919. LONG lResult;
  1920. DWORD dataType;
  1921. DWORD dataSize;
  1922. DWORD data;
  1923. lResult = RegOpenKey (HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Applets\\SysTray"), &key);
  1924. if ((lResult == ERROR_SUCCESS) && key) {
  1925. dataSize = 0;
  1926. lResult = RegQueryValueEx (key, TEXT("Services"), NULL, &dataType, NULL, &dataSize);
  1927. if ((lResult == ERROR_SUCCESS) && (dataType == REG_DWORD)) {
  1928. lResult = RegQueryValueEx (key, TEXT("Services"), NULL, &dataType, (LPBYTE)(&data), &dataSize);
  1929. if (lResult == ERROR_SUCCESS) {
  1930. g_OFStatus = ((data & 0x00000008) != 0);
  1931. }
  1932. }
  1933. CloseHandle (key);
  1934. }
  1935. }
  1936. VOID
  1937. RebootOnOFStatusChange (
  1938. IN HINSTANCE Instance,
  1939. IN HWND hwndDlg,
  1940. IN PCTSTR Args
  1941. )
  1942. {
  1943. HKEY key = NULL;
  1944. LONG lResult;
  1945. DWORD dataType;
  1946. DWORD dataSize;
  1947. DWORD data;
  1948. lResult = RegOpenKey (HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Applets\\SysTray"), &key);
  1949. if ((lResult == ERROR_SUCCESS) && key) {
  1950. dataSize = 0;
  1951. lResult = RegQueryValueEx (key, TEXT("Services"), NULL, &dataType, NULL, &dataSize);
  1952. if ((lResult == ERROR_SUCCESS) && (dataType == REG_DWORD)) {
  1953. lResult = RegQueryValueEx (key, TEXT("Services"), NULL, &dataType, (LPBYTE)(&data), &dataSize);
  1954. if (lResult == ERROR_SUCCESS) {
  1955. if (g_OFStatus && ((data & 0x00000008) == 0)) {
  1956. AskForReboot (Instance, hwndDlg, NULL);
  1957. }
  1958. if ((!g_OFStatus) && ((data & 0x00000008) != 0)) {
  1959. AskForReboot (Instance, hwndDlg, NULL);
  1960. }
  1961. }
  1962. }
  1963. CloseHandle (key);
  1964. }
  1965. }
  1966. typedef BOOL (WINAPI LOCKSETFOREGROUNDWINDOW)(UINT uLockCode);
  1967. typedef LOCKSETFOREGROUNDWINDOW *PLOCKSETFOREGROUNDWINDOW;
  1968. VOID
  1969. RestartExplorer (
  1970. IN HINSTANCE Instance,
  1971. IN HWND hwndDlg,
  1972. IN PCTSTR Args
  1973. )
  1974. {
  1975. BOOL bResult;
  1976. STARTUPINFO si;
  1977. PROCESS_INFORMATION pi;
  1978. HMODULE lib;
  1979. PLOCKSETFOREGROUNDWINDOW dynLockSetForegroundWindow;
  1980. if (g_Explorer) {
  1981. //
  1982. // Start explorer.exe
  1983. //
  1984. ZeroMemory( &si, sizeof(STARTUPINFO) );
  1985. si.cb = sizeof(STARTUPINFO);
  1986. lib = LoadLibrary (TEXT("user32.dll"));
  1987. if (lib) {
  1988. dynLockSetForegroundWindow = (PLOCKSETFOREGROUNDWINDOW) GetProcAddress (lib, "LockSetForegroundWindow");
  1989. if (dynLockSetForegroundWindow) {
  1990. // let's lock this so Explorer does not steal our focus
  1991. dynLockSetForegroundWindow (LSFW_LOCK);
  1992. }
  1993. FreeLibrary (lib);
  1994. }
  1995. bResult = CreateProcess(
  1996. NULL,
  1997. g_Explorer,
  1998. NULL,
  1999. NULL,
  2000. FALSE,
  2001. CREATE_NEW_PROCESS_GROUP,
  2002. NULL,
  2003. NULL,
  2004. &si,
  2005. &pi
  2006. );
  2007. if (bResult) {
  2008. CloseHandle (pi.hProcess);
  2009. CloseHandle (pi.hThread);
  2010. }
  2011. }
  2012. }
  2013. BOOL
  2014. AppExecute (
  2015. IN HINSTANCE Instance,
  2016. IN HWND hwndDlg,
  2017. IN PCTSTR ExecuteArgs
  2018. )
  2019. {
  2020. PCTSTR funcName = NULL;
  2021. PCTSTR funcArgs = NULL;
  2022. funcName = ExecuteArgs;
  2023. if (!funcName || !(*funcName)) {
  2024. return FALSE;
  2025. }
  2026. funcArgs = StrChrI (funcName, 0);
  2027. if (funcArgs) {
  2028. funcArgs ++;
  2029. if (!(*funcArgs)) {
  2030. funcArgs = NULL;
  2031. }
  2032. }
  2033. // BUGBUG - temporary, make a macro expansion list out of it
  2034. if (0 == StrCmpI (funcName, TEXT("KillExplorer"))) {
  2035. KillExplorer (Instance, hwndDlg, funcArgs);
  2036. }
  2037. if (0 == StrCmpI (funcName, TEXT("RefreshMetrics"))) {
  2038. RefreshMetrics (Instance, hwndDlg, funcArgs);
  2039. }
  2040. if (0 == StrCmpI (funcName, TEXT("AskForLogOff"))) {
  2041. AskForLogOff (Instance, hwndDlg, funcArgs);
  2042. }
  2043. if (0 == StrCmpI (funcName, TEXT("AskForReboot"))) {
  2044. AskForReboot (Instance, hwndDlg, funcArgs);
  2045. }
  2046. if (0 == StrCmpI (funcName, TEXT("RestartExplorer"))) {
  2047. RestartExplorer (Instance, hwndDlg, funcArgs);
  2048. }
  2049. if (0 == StrCmpI (funcName, TEXT("SwitchToClassicDesktop"))) {
  2050. SwitchToClassicDesktop (Instance, hwndDlg, funcArgs);
  2051. }
  2052. if (0 == StrCmpI (funcName, TEXT("SwitchToClassicTaskBar"))) {
  2053. SwitchToClassicTaskBar (Instance, hwndDlg, funcArgs);
  2054. }
  2055. if (0 == StrCmpI (funcName, TEXT("RegisterFonts"))) {
  2056. RegisterFonts (Instance, hwndDlg, funcArgs);
  2057. }
  2058. if (0 == StrCmpI (funcName, TEXT("SaveOFStatus"))) {
  2059. SaveOFStatus (Instance, hwndDlg, funcArgs);
  2060. }
  2061. if (0 == StrCmpI (funcName, TEXT("RebootOnOFStatusChange"))) {
  2062. RebootOnOFStatusChange (Instance, hwndDlg, funcArgs);
  2063. }
  2064. return TRUE;
  2065. }
  2066. ////////////////////////////////////////////////////
  2067. //
  2068. // Obtaining a connection point sink is supposed to be easy. You just
  2069. // QI for the interface. Unfortunately, too many components are buggy.
  2070. //
  2071. // mmc.exe faults if you QI for IDispatch
  2072. // and punkCB is non-NULL. And if you do pass in NULL,
  2073. // it returns S_OK but fills punkCB with NULL anyway.
  2074. // Somebody must've had a rough day.
  2075. //
  2076. // Java responds only to its dispatch ID and not IID_IDispatch, even
  2077. // though the dispatch ID is derived from IID_IDispatch.
  2078. //
  2079. // The Explorer Band responds only to IID_IDispatch and not to
  2080. // the dispatch ID.
  2081. //
  2082. HRESULT GetConnectionPointSink(IUnknown *pUnk, const IID *piidCB, IUnknown **ppunkCB)
  2083. {
  2084. HRESULT hr = E_NOINTERFACE;
  2085. *ppunkCB = NULL; // Pre-zero it to work around MMC
  2086. if (piidCB) // Optional interface (Java/ExplBand)
  2087. {
  2088. hr = pUnk->QueryInterface(*piidCB, (void **) ppunkCB);
  2089. if (*ppunkCB == NULL) // Clean up behind MMC
  2090. hr = E_NOINTERFACE;
  2091. }
  2092. return hr;
  2093. }
  2094. //
  2095. // Enumerate the connection point sinks, calling the callback for each one
  2096. // found.
  2097. //
  2098. // The callback function is called once for each sink. The IUnknown is
  2099. // whatever interface we could get from the sink (either piidCB or piidCB2).
  2100. //
  2101. typedef HRESULT (CALLBACK *ENUMCONNECTIONPOINTSPROC)(
  2102. /* [in, iid_is(*piidCB)] */ IUnknown *psink, LPARAM lParam);
  2103. HRESULT EnumConnectionPointSinks(
  2104. IConnectionPoint *pcp, // IConnectionPoint victim
  2105. const IID *piidCB, // Interface for callback
  2106. const IID *piidCB2, // Alternate interface for callback
  2107. ENUMCONNECTIONPOINTSPROC EnumProc, // Callback procedure
  2108. LPARAM lParam) // Refdata for callback
  2109. {
  2110. HRESULT hr;
  2111. IEnumConnections * pec;
  2112. if (pcp)
  2113. hr = pcp->EnumConnections(&pec);
  2114. else
  2115. hr = E_NOINTERFACE;
  2116. if (SUCCEEDED(hr))
  2117. {
  2118. CONNECTDATA cd;
  2119. ULONG cFetched;
  2120. while (S_OK == (hr = pec->Next(1, &cd, &cFetched)))
  2121. {
  2122. IUnknown *punkCB;
  2123. //ASSERT(1 == cFetched);
  2124. hr = GetConnectionPointSink(cd.pUnk, piidCB, &punkCB);
  2125. if (FAILED(hr))
  2126. hr = GetConnectionPointSink(cd.pUnk, piidCB2, &punkCB);
  2127. if (SUCCEEDED(hr))
  2128. {
  2129. hr = EnumProc(punkCB, lParam);
  2130. punkCB->Release();
  2131. }
  2132. else
  2133. {
  2134. hr = S_OK; // Pretend callback succeeded
  2135. }
  2136. cd.pUnk->Release();
  2137. if (FAILED(hr)) break; // Callback asked to stop
  2138. }
  2139. pec->Release();
  2140. hr = S_OK;
  2141. }
  2142. return hr;
  2143. }
  2144. //
  2145. // Send out the callback (if applicable) and then do the invoke if the
  2146. // callback said that was a good idea.
  2147. //
  2148. // Parameters:
  2149. //
  2150. // pcp - IConnectionPoint whose sinks are to be Invoke()d.
  2151. // If this parameter is NULL, the function does nothing.
  2152. // pinv - Structure containing parameters to INVOKE.
  2153. HRESULT CALLBACK EnumInvokeCallback(IUnknown *psink, LPARAM lParam)
  2154. {
  2155. IDispatch *pdisp = (IDispatch *)psink;
  2156. LPSHINVOKEPARAMS pinv = (LPSHINVOKEPARAMS)lParam;
  2157. HRESULT hr;
  2158. if (pinv->Callback)
  2159. {
  2160. // Now see if the callback wants to do pre-vet the pdisp.
  2161. // It can return S_FALSE to skip this callback or E_FAIL to
  2162. // stop the invoke altogether
  2163. hr = pinv->Callback(pdisp, pinv);
  2164. if (hr != S_OK) return hr;
  2165. }
  2166. pdisp->Invoke(pinv->dispidMember, *pinv->piid, pinv->lcid,
  2167. pinv->wFlags, pinv->pdispparams, pinv->pvarResult,
  2168. pinv->pexcepinfo, pinv->puArgErr);
  2169. return S_OK;
  2170. }
  2171. //
  2172. // QI's for IConnectionPointContainer and then does the FindConnectionPoint.
  2173. //
  2174. // Parameters:
  2175. //
  2176. // punk - The object who might be an IConnectionPointContainer.
  2177. // This parameter may be NULL, in which case the
  2178. // operation fails.
  2179. // riidCP - The connection point interface to locate.
  2180. // pcpOut - Receives the IConnectionPoint, if any.
  2181. HRESULT IUnknown_FindConnectionPoint(IUnknown *punk, REFIID riidCP,
  2182. IConnectionPoint **pcpOut)
  2183. {
  2184. HRESULT hr;
  2185. *pcpOut = NULL;
  2186. if (punk)
  2187. {
  2188. IConnectionPointContainer *pcpc;
  2189. hr = punk->QueryInterface(IID_IConnectionPointContainer, (void **)&pcpc);
  2190. if (SUCCEEDED(hr))
  2191. {
  2192. hr = pcpc->FindConnectionPoint(riidCP, pcpOut);
  2193. pcpc->Release();
  2194. }
  2195. }
  2196. else
  2197. hr = E_NOINTERFACE;
  2198. return hr;
  2199. }
  2200. //
  2201. // IConnectionPoint_InvokeIndirect
  2202. //
  2203. // Given a connection point, call the IDispatch::Invoke for each
  2204. // connected sink.
  2205. //
  2206. // The return value merely indicates whether the command was dispatched.
  2207. // If any particular sink fails the IDispatch::Invoke, we will still
  2208. // return S_OK, since the command was indeed dispatched.
  2209. //
  2210. // Parameters:
  2211. //
  2212. // pcp - IConnectionPoint whose sinks are to be Invoke()d.
  2213. // If this parameter is NULL, the function does nothing.
  2214. // pinv - Structure containing parameters to INVOKE.
  2215. // The pdispparams field can be NULL; we will turn it
  2216. // into a real DISPPARAMS for you.
  2217. //
  2218. // The SHINVOKEPARAMS.flags field can contain the following flags.
  2219. //
  2220. // IPFL_USECALLBACK - The callback field contains a callback function
  2221. // Otherwise, it will be set to NULL.
  2222. // IPFL_USEDEFAULT - Many fields in the SHINVOKEPARAMS will be set to
  2223. // default values to save the caller effort:
  2224. //
  2225. // riid = IID_NULL
  2226. // lcid = 0
  2227. // wFlags = DISPATCH_METHOD
  2228. // pvarResult = NULL
  2229. // pexcepinfo = NULL
  2230. // puArgErr = NULL
  2231. //
  2232. HRESULT IConnectionPoint_InvokeIndirect(
  2233. IConnectionPoint *pcp,
  2234. SHINVOKEPARAMS *pinv)
  2235. {
  2236. HRESULT hr;
  2237. DISPPARAMS dp = { 0 };
  2238. IID iidCP;
  2239. if (pinv->pdispparams == NULL)
  2240. pinv->pdispparams = &dp;
  2241. if (!(pinv->flags & IPFL_USECALLBACK))
  2242. {
  2243. pinv->Callback = NULL;
  2244. }
  2245. if (pinv->flags & IPFL_USEDEFAULTS)
  2246. {
  2247. pinv->piid = &IID_NULL;
  2248. pinv->lcid = 0;
  2249. pinv->wFlags = DISPATCH_METHOD;
  2250. pinv->pvarResult = NULL;
  2251. pinv->pexcepinfo = NULL;
  2252. pinv->puArgErr = NULL;
  2253. }
  2254. // Try both the interface they actually connected on,
  2255. // as well as IDispatch. Apparently Java responds only to
  2256. // the connecting interface, and ExplBand responds only to
  2257. // IDispatch, so we have to try both. (Sigh. Too many buggy
  2258. // components in the system.)
  2259. hr = EnumConnectionPointSinks(pcp,
  2260. (pcp->GetConnectionInterface(&iidCP) == S_OK) ? &iidCP : NULL,
  2261. &IID_IDispatch,
  2262. EnumInvokeCallback,
  2263. (LPARAM)pinv);
  2264. // Put the original NULL back so the caller can re-use the SHINVOKEPARAMS.
  2265. if (pinv->pdispparams == &dp)
  2266. pinv->pdispparams = NULL;
  2267. return hr;
  2268. }
  2269. //
  2270. // Given an IUnknown, query for its connection point container,
  2271. // find the corresponding connection point, package up the
  2272. // invoke parameters, and call the IDispatch::Invoke for each
  2273. // connected sink.
  2274. //
  2275. // See IConnectionPoint_InvokeParam for additional semantics.
  2276. //
  2277. // Parameters:
  2278. //
  2279. // punk - Object that might be an IConnectionPointContainer
  2280. // riidCP - ConnectionPoint interface to request
  2281. // pinv - Arguments for the Invoke.
  2282. //
  2283. HRESULT IUnknown_CPContainerInvokeIndirect(IUnknown *punk, REFIID riidCP,
  2284. SHINVOKEPARAMS *pinv)
  2285. {
  2286. IConnectionPoint *pcp;
  2287. HRESULT hr = IUnknown_FindConnectionPoint(punk, riidCP, &pcp);
  2288. if (SUCCEEDED(hr))
  2289. {
  2290. hr = IConnectionPoint_InvokeIndirect(pcp, pinv);
  2291. pcp->Release();
  2292. }
  2293. return hr;
  2294. }
  2295. //////////////////////////////////////////////////////////////////////////////////////
  2296. VOID
  2297. _UpdateText(
  2298. IN HWND hWnd,
  2299. IN LPCTSTR pcszString
  2300. )
  2301. {
  2302. TCHAR szCurString[MAX_LOADSTRING];
  2303. if (pcszString)
  2304. {
  2305. SendMessage (hWnd, WM_GETTEXT, (WPARAM)MAX_LOADSTRING, (LPARAM)szCurString);
  2306. if (StrCmp (pcszString, szCurString))
  2307. {
  2308. SendMessage (hWnd, WM_SETTEXT, 0, (LPARAM)pcszString);
  2309. }
  2310. }
  2311. }
  2312. //////////////////////////////////////////////////////////////////////////////////////
  2313. VOID
  2314. _RemoveSpaces (
  2315. IN PTSTR szData,
  2316. IN UINT uDataCount
  2317. )
  2318. {
  2319. UINT curr;
  2320. PTSTR currPtr;
  2321. PTSTR lastSpace;
  2322. BOOL isSpace;
  2323. // First trim the spaces at the beginning
  2324. if (!szData) {
  2325. return;
  2326. }
  2327. curr = _tcsnextc (szData);
  2328. while (curr == TEXT(' ')) {
  2329. currPtr = _tcsinc (szData);
  2330. memmove (szData, currPtr, uDataCount * sizeof(TCHAR) - (UINT)((currPtr - szData) * sizeof (TCHAR)));
  2331. curr = _tcsnextc (szData);
  2332. }
  2333. // Now trim the trailing spaces
  2334. lastSpace = NULL;
  2335. currPtr = szData;
  2336. curr = _tcsnextc (szData);
  2337. while (curr) {
  2338. if (curr == TEXT(' ')) {
  2339. if (!lastSpace) {
  2340. lastSpace = currPtr;
  2341. }
  2342. } else {
  2343. if (lastSpace) {
  2344. lastSpace = NULL;
  2345. }
  2346. }
  2347. currPtr = _tcsinc (currPtr);
  2348. curr = _tcsnextc (currPtr);
  2349. }
  2350. if (lastSpace) {
  2351. *lastSpace = 0;
  2352. }
  2353. }
  2354. POBJLIST
  2355. _AllocateObjectList (
  2356. IN PCTSTR ObjectName
  2357. )
  2358. {
  2359. POBJLIST objList;
  2360. objList = (POBJLIST)LocalAlloc (LPTR, sizeof (OBJLIST));
  2361. if (objList) {
  2362. ZeroMemory (objList, sizeof (OBJLIST));
  2363. objList->ObjectName = (PTSTR)LocalAlloc (LPTR, (_tcslen (ObjectName) + 1) * sizeof (TCHAR));
  2364. if (objList->ObjectName) {
  2365. _tcscpy (objList->ObjectName, ObjectName);
  2366. }
  2367. }
  2368. return objList;
  2369. }
  2370. VOID
  2371. pFreeObjects (
  2372. IN POBJLIST ObjectList
  2373. )
  2374. {
  2375. if (ObjectList->Next) {
  2376. pFreeObjects(ObjectList->Next);
  2377. LocalFree(ObjectList->Next);
  2378. ObjectList->Next = NULL;
  2379. }
  2380. if (ObjectList->ObjectName) {
  2381. LocalFree(ObjectList->ObjectName);
  2382. ObjectList->ObjectName = NULL;
  2383. }
  2384. }
  2385. VOID
  2386. _FreeObjectList (
  2387. IN POBJLIST ObjectList
  2388. )
  2389. {
  2390. if (ObjectList) {
  2391. pFreeObjects(ObjectList);
  2392. LocalFree(ObjectList);
  2393. }
  2394. }