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.

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