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.

698 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: util.cpp
  4. //
  5. // Description:
  6. //
  7. // Copyright (c) 2000 Microsoft Corp.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. // App Includes
  11. #include "precomp.h"
  12. #include "main.h"
  13. #include "resource.h"
  14. #include <shlobj.h>
  15. #include <shfolder.h>
  16. ////////////////////////// Function Prototypes ////////////////////////////////
  17. int CALLBACK ChangeDirectoryCallback(HWND hWnd,
  18. UINT uMsg,
  19. LPARAM lParam,
  20. LPARAM lpData);
  21. ///////////////////////////
  22. // GVAR_LOCAL
  23. //
  24. // Global Variable
  25. //
  26. static struct GVAR_LOCAL
  27. {
  28. HKEY hRootKey;
  29. } GVAR_LOCAL =
  30. {
  31. NULL
  32. };
  33. ///////////////////////////////
  34. // Util::Init
  35. //
  36. HRESULT Util::Init(HINSTANCE hInstance)
  37. {
  38. HRESULT hr = S_OK;
  39. if (SUCCEEDED(hr))
  40. {
  41. LRESULT lr = NOERROR;
  42. DWORD dwDisposition = 0;
  43. lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  44. REG_KEY_PROJECTOR,
  45. NULL,
  46. NULL,
  47. 0,
  48. KEY_ALL_ACCESS,
  49. NULL,
  50. &GVAR_LOCAL.hRootKey,
  51. &dwDisposition);
  52. if (lr != NOERROR)
  53. {
  54. DBG_ERR(("InitApp, failed to open registry key"));
  55. hr = E_FAIL;
  56. }
  57. }
  58. return hr;
  59. }
  60. ///////////////////////////////
  61. // Util::Term
  62. //
  63. HRESULT Util::Term(void)
  64. {
  65. RegCloseKey(GVAR_LOCAL.hRootKey);
  66. GVAR_LOCAL.hRootKey = NULL;
  67. return S_OK;
  68. }
  69. ///////////////////////////////
  70. // GetMyPicturesFolder
  71. //
  72. HRESULT Util::GetMyPicturesFolder(TCHAR *pszFolder,
  73. DWORD cchFolder)
  74. {
  75. HRESULT hr = S_OK;
  76. // set the directory of the images.
  77. hr = SHGetFolderPath(NULL,
  78. CSIDL_MYPICTURES,
  79. NULL,
  80. 0,
  81. pszFolder);
  82. return hr;
  83. }
  84. ///////////////////////////////
  85. // GetProgramFilesFolder
  86. //
  87. HRESULT Util::GetProgramFilesFolder(TCHAR *pszFolder,
  88. DWORD cchFolder)
  89. {
  90. HRESULT hr = S_OK;
  91. // set the directory of the images.
  92. hr = SHGetFolderPath(NULL,
  93. CSIDL_PROGRAM_FILES,
  94. NULL,
  95. 0,
  96. pszFolder);
  97. return hr;
  98. }
  99. ///////////////////////////////
  100. // Util::GetAppDirs
  101. //
  102. HRESULT Util::GetAppDirs(TCHAR *pszDeviceDir,
  103. DWORD cchDeviceDir,
  104. TCHAR *pszImageDir,
  105. DWORD cchImageDir)
  106. {
  107. HRESULT hr = S_OK;
  108. ASSERT(pszDeviceDir != NULL);
  109. ASSERT(pszImageDir != NULL);
  110. ASSERT(cchDeviceDir > 0);
  111. ASSERT(cchImageDir > 0);
  112. if ((pszDeviceDir == NULL) ||
  113. (pszImageDir == NULL) ||
  114. (cchDeviceDir == 0) ||
  115. (cchImageDir == 0))
  116. {
  117. return E_INVALIDARG;
  118. }
  119. // preload the image dir buffer with the "My Pictures" path
  120. // so that it is set as the default directory if we don't
  121. // have an overriding one in the registry.
  122. if (SUCCEEDED(hr))
  123. {
  124. hr = GetMyPicturesFolder(pszImageDir,
  125. cchImageDir);
  126. }
  127. // preload the device dir buffer with the "Program Files\MSProjector"
  128. // install path so that it is set as the default directory if we don't
  129. // have an overriding one in the registry.
  130. if (SUCCEEDED(hr))
  131. {
  132. hr = GetProgramFilesFolder(pszDeviceDir,
  133. cchDeviceDir);
  134. }
  135. if (SUCCEEDED(hr))
  136. {
  137. if (pszDeviceDir[_tcslen(pszDeviceDir) - 1] != '\\')
  138. {
  139. _tcscat(pszDeviceDir, _T("\\"));
  140. }
  141. _tcscat(pszDeviceDir, DEFAULT_INSTALL_PATH);
  142. }
  143. if (SUCCEEDED(hr))
  144. {
  145. // get the image dir.
  146. hr = GetRegString(REG_VAL_IMAGE_DIR,
  147. pszImageDir,
  148. cchImageDir,
  149. TRUE);
  150. if (FAILED(hr))
  151. {
  152. DBG_ERR(("GetAppDirs, failed to get/set image directory. "
  153. "This should never happen"));
  154. ASSERT(FALSE);
  155. }
  156. // get the device dir
  157. hr = GetRegString(REG_VAL_DEVICE_DIR,
  158. pszDeviceDir,
  159. cchDeviceDir,
  160. TRUE);
  161. if (FAILED(hr))
  162. {
  163. DBG_ERR(("GetAppDirs, failed to get/set image directory. "
  164. "This should never happen"));
  165. ASSERT(FALSE);
  166. }
  167. }
  168. return hr;
  169. }
  170. ///////////////////////////////
  171. // Util::GetRegString
  172. //
  173. HRESULT Util::GetRegString(const TCHAR *pszValueName,
  174. TCHAR *pszDir,
  175. DWORD cchDir,
  176. BOOL bSetIfNotExist)
  177. {
  178. HRESULT hr = S_OK;
  179. ASSERT(pszValueName != NULL);
  180. ASSERT(pszDir != NULL);
  181. ASSERT(cchDir > 0);
  182. if ((pszValueName == NULL) ||
  183. (pszDir == NULL) ||
  184. (cchDir <= 0))
  185. {
  186. return E_INVALIDARG;
  187. }
  188. if (SUCCEEDED(hr))
  189. {
  190. LRESULT lr = NOERROR;
  191. DWORD dwType = REG_SZ;
  192. lr = RegQueryValueEx(GVAR_LOCAL.hRootKey,
  193. pszValueName,
  194. NULL,
  195. &dwType,
  196. (BYTE*) pszDir,
  197. &cchDir);
  198. if (lr != NOERROR)
  199. {
  200. if (bSetIfNotExist)
  201. {
  202. // we need the number of bytes we are writing to the registry.
  203. DWORD dwLength = _tcslen(pszDir) * sizeof(TCHAR) + 1;
  204. lr = RegSetValueEx(GVAR_LOCAL.hRootKey,
  205. pszValueName,
  206. NULL,
  207. REG_SZ,
  208. (BYTE*) pszDir,
  209. dwLength);
  210. }
  211. else
  212. {
  213. hr = E_FAIL;
  214. DBG_ERR(("GetRegString, failed to get '%ls' from registry, hr = 0x%08lx",
  215. pszValueName,
  216. hr));
  217. }
  218. }
  219. }
  220. return hr;
  221. }
  222. ///////////////////////////////
  223. // Util::SetRegString
  224. //
  225. HRESULT Util::SetRegString(const TCHAR *pszValueName,
  226. TCHAR *pszDir,
  227. DWORD cchDir)
  228. {
  229. HRESULT hr = S_OK;
  230. ASSERT(pszValueName != NULL);
  231. ASSERT(pszDir != NULL);
  232. ASSERT(cchDir > 0);
  233. if ((pszValueName == NULL) ||
  234. (pszDir == NULL) ||
  235. (cchDir <= 0))
  236. {
  237. return E_INVALIDARG;
  238. }
  239. if (SUCCEEDED(hr))
  240. {
  241. LRESULT lr = NOERROR;
  242. DWORD dwLength = _tcslen(pszDir) * sizeof(TCHAR) + 1;
  243. // we need the number of bytes we are writing to the registry.
  244. lr = RegSetValueEx(GVAR_LOCAL.hRootKey,
  245. pszValueName,
  246. NULL,
  247. REG_SZ,
  248. (BYTE*) pszDir,
  249. dwLength);
  250. if (lr != NOERROR)
  251. {
  252. hr = E_FAIL;
  253. DBG_ERR(("SetRegString, failed to set '%ls' to registry, hr = 0x%08lx",
  254. pszValueName,
  255. hr));
  256. }
  257. }
  258. return hr;
  259. }
  260. ///////////////////////////////
  261. // Util::GetRegDWORD
  262. //
  263. HRESULT Util::GetRegDWORD(const TCHAR *pszValueName,
  264. DWORD *pdwValue,
  265. BOOL bSetIfNotExist)
  266. {
  267. HRESULT hr = S_OK;
  268. ASSERT(pszValueName != NULL);
  269. ASSERT(pdwValue != NULL);
  270. if ((pszValueName == NULL) ||
  271. (pdwValue == NULL))
  272. {
  273. return E_INVALIDARG;
  274. }
  275. if (SUCCEEDED(hr))
  276. {
  277. LRESULT lr = NOERROR;
  278. DWORD dwType = REG_DWORD;
  279. DWORD dwSize = sizeof(DWORD);
  280. lr = RegQueryValueEx(GVAR_LOCAL.hRootKey,
  281. pszValueName,
  282. NULL,
  283. &dwType,
  284. (BYTE*) pdwValue,
  285. &dwSize);
  286. if (lr != NOERROR)
  287. {
  288. if (bSetIfNotExist)
  289. {
  290. // we need the number of bytes we are writing to the registry.
  291. lr = RegSetValueEx(GVAR_LOCAL.hRootKey,
  292. pszValueName,
  293. NULL,
  294. REG_SZ,
  295. (BYTE*) pdwValue,
  296. dwSize);
  297. }
  298. else
  299. {
  300. hr = E_FAIL;
  301. DBG_ERR(("GetRegDWORD, failed to get '%ls' from registry, hr = 0x%08lx",
  302. pszValueName,
  303. hr));
  304. }
  305. }
  306. }
  307. return hr;
  308. }
  309. ///////////////////////////////
  310. // Util::SetRegDWORD
  311. //
  312. HRESULT Util::SetRegDWORD(const TCHAR *pszValueName,
  313. DWORD dwValue)
  314. {
  315. HRESULT hr = S_OK;
  316. ASSERT(pszValueName != NULL);
  317. if (pszValueName == NULL)
  318. {
  319. return E_INVALIDARG;
  320. }
  321. if (SUCCEEDED(hr))
  322. {
  323. LRESULT lr = NOERROR;
  324. // we need the number of bytes we are writing to the registry.
  325. lr = RegSetValueEx(GVAR_LOCAL.hRootKey,
  326. pszValueName,
  327. NULL,
  328. REG_DWORD,
  329. (BYTE*) &dwValue,
  330. sizeof(DWORD));
  331. if (lr != NOERROR)
  332. {
  333. hr = E_FAIL;
  334. DBG_ERR(("SetRegDWORD, failed to set '%ls' to registry, hr = 0x%08lx",
  335. pszValueName,
  336. hr));
  337. }
  338. }
  339. return hr;
  340. }
  341. ///////////////////////////////
  342. // Util::BrowseForDirectory
  343. //
  344. bool Util::BrowseForDirectory(HWND hWnd,
  345. const TCHAR *pszPrompt,
  346. TCHAR *pszDirectory,
  347. DWORD cchDirectory)
  348. {
  349. bool bResult = false;
  350. LPMALLOC pMalloc = NULL;
  351. LPITEMIDLIST pidlSharedPictures = NULL;
  352. HRESULT hr = SHGetMalloc(&pMalloc);
  353. if (SUCCEEDED(hr))
  354. {
  355. hr = SHGetFolderLocation(NULL,
  356. CSIDL_COMMON_PICTURES,
  357. NULL,
  358. 0,
  359. &pidlSharedPictures);
  360. }
  361. if (SUCCEEDED(hr))
  362. {
  363. TCHAR szDisplayName[_MAX_PATH + 1] = {0};
  364. TCHAR szDirectory[_MAX_PATH + 1] = {0};
  365. BROWSEINFO BrowseInfo = {0};
  366. BrowseInfo.hwndOwner = hWnd;
  367. BrowseInfo.pidlRoot = pidlSharedPictures;
  368. BrowseInfo.pszDisplayName = szDisplayName;
  369. BrowseInfo.lpszTitle = pszPrompt;
  370. BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
  371. BrowseInfo.lpfn = ChangeDirectoryCallback;
  372. BrowseInfo.lParam = (LPARAM)szDirectory;
  373. BrowseInfo.iImage = 0;
  374. LPITEMIDLIST pidl = SHBrowseForFolder(&BrowseInfo);
  375. if (pidl != NULL)
  376. {
  377. TCHAR szResult[MAX_PATH + 1] = {0};
  378. if (SHGetPathFromIDList(pidl, szResult))
  379. {
  380. _tcsncpy(pszDirectory, szResult, cchDirectory);
  381. bResult = true;
  382. }
  383. pMalloc->Free(pidl);
  384. pidl = NULL;
  385. }
  386. }
  387. if (pidlSharedPictures)
  388. {
  389. pMalloc->Free(pidlSharedPictures);
  390. pidlSharedPictures = NULL;
  391. }
  392. if (pMalloc)
  393. {
  394. pMalloc->Release();
  395. pMalloc = NULL;
  396. }
  397. return bResult;
  398. }
  399. ///////////////////////////////
  400. // ChangeDirectoryCallback
  401. //
  402. int CALLBACK ChangeDirectoryCallback(HWND hWnd,
  403. UINT uMsg,
  404. LPARAM lParam,
  405. LPARAM lpData )
  406. {
  407. if (uMsg == BFFM_INITIALIZED)
  408. {
  409. SendMessage(hWnd, BFFM_SETSELECTION, 1, (LPARAM)lpData );
  410. }
  411. return 0;
  412. }
  413. ///////////////////////////////
  414. // Util::FormatTime
  415. //
  416. HRESULT Util::FormatTime(HINSTANCE hInstance,
  417. UINT nTotalSeconds,
  418. TCHAR *pszTime,
  419. DWORD cchTime)
  420. {
  421. ASSERT(pszTime != NULL);
  422. HRESULT hr = S_OK;
  423. int iResult = 0;
  424. TCHAR szString[255 + 1] = {0};
  425. UINT nMinutes = nTotalSeconds / 60;
  426. UINT nSeconds = nTotalSeconds % 60;
  427. UINT uiStrResID = 0;
  428. if (pszTime == NULL)
  429. {
  430. return E_INVALIDARG;
  431. }
  432. if (nMinutes == 0)
  433. {
  434. if (nSeconds == 1)
  435. {
  436. uiStrResID = IDS_SECOND;
  437. }
  438. else
  439. {
  440. uiStrResID = IDS_SECONDS;
  441. }
  442. }
  443. else if (nSeconds == 0)
  444. {
  445. if (nMinutes == 1)
  446. {
  447. uiStrResID = IDS_MINUTE;
  448. }
  449. else
  450. {
  451. uiStrResID = IDS_MINUTES;
  452. }
  453. }
  454. else if ((nMinutes == 1) && (nSeconds == 1))
  455. {
  456. uiStrResID = IDS_MINUTE_AND_SECOND;
  457. }
  458. else if (nMinutes == 1)
  459. {
  460. uiStrResID = IDS_MINUTE_AND_SECONDS;
  461. }
  462. else if (nSeconds == 1)
  463. {
  464. uiStrResID = IDS_MINUTES_AND_SECOND;
  465. }
  466. else
  467. {
  468. uiStrResID = IDS_MINUTES_AND_SECONDS;
  469. }
  470. if (uiStrResID != 0)
  471. {
  472. iResult = ::LoadString(hInstance,
  473. uiStrResID,
  474. szString,
  475. sizeof(szString) / sizeof(TCHAR));
  476. }
  477. if (iResult != 0)
  478. {
  479. if (nMinutes == 0)
  480. {
  481. _sntprintf(pszTime, cchTime, szString, nSeconds);
  482. }
  483. else if (nSeconds == 0)
  484. {
  485. _sntprintf(pszTime, cchTime, szString, nMinutes);
  486. }
  487. else
  488. {
  489. _sntprintf(pszTime, cchTime, szString, nMinutes, nSeconds);
  490. }
  491. }
  492. return hr;
  493. }
  494. ///////////////////////////////
  495. // Util::FormatScale
  496. //
  497. HRESULT Util::FormatScale(HINSTANCE hInstance,
  498. DWORD dwImageScaleFactor,
  499. TCHAR *pszScale,
  500. DWORD cchScale)
  501. {
  502. ASSERT(pszScale != NULL);
  503. HRESULT hr = S_OK;
  504. int iResult = 0;
  505. TCHAR szString[255 + 1] = {0};
  506. UINT uiStrResID = IDS_PERCENT;
  507. if (pszScale == NULL)
  508. {
  509. return E_INVALIDARG;
  510. }
  511. if (uiStrResID != 0)
  512. {
  513. iResult = ::LoadString(hInstance,
  514. uiStrResID,
  515. szString,
  516. sizeof(szString) / sizeof(TCHAR));
  517. }
  518. if (iResult != 0)
  519. {
  520. _sntprintf(pszScale, cchScale, szString, dwImageScaleFactor);
  521. }
  522. return hr;
  523. }
  524. ///////////////////////////////
  525. // EndsWithChar
  526. //
  527. static BOOL EndsWithChar( LPCTSTR psz, TCHAR c )
  528. {
  529. TCHAR* pszLast = _tcsrchr( (TCHAR*)psz, c ); // find last occurence of char in psz
  530. return(( NULL != pszLast ) && ( *_tcsinc( pszLast ) == _T('\0') ) );
  531. }
  532. ///////////////////////////////
  533. // StripTrailingChar
  534. //
  535. static void StripTrailingChar(TCHAR* input, TCHAR c)
  536. {
  537. while (EndsWithChar(input, c))
  538. {
  539. TCHAR* p = input + _tcsclen(input) - 1;
  540. *p = _T('\0');
  541. }
  542. return;
  543. }
  544. ///////////////////////////////
  545. // GetString
  546. //
  547. BOOL Util::GetString(HINSTANCE hInstance,
  548. INT iStrResID,
  549. TCHAR *pszString,
  550. DWORD cchString,
  551. ...)
  552. {
  553. TCHAR szFmtString[255 + 1] = {0};
  554. INT iResult = 0;
  555. va_list vaList;
  556. BOOL bSuccess = FALSE;
  557. iResult = ::LoadString(hInstance,
  558. iStrResID,
  559. szFmtString,
  560. sizeof(szFmtString) / sizeof(TCHAR));
  561. if (iResult != 0)
  562. {
  563. va_start(vaList, cchString);
  564. _vsntprintf(pszString, cchString - 1, szFmtString, vaList);
  565. va_end(vaList);
  566. bSuccess = TRUE;
  567. }
  568. else
  569. {
  570. bSuccess = FALSE;
  571. }
  572. return bSuccess;
  573. }
  574. ///////////////////////////////
  575. // DoesDirExist
  576. //
  577. BOOL Util::DoesDirExist( LPCTSTR pszPath )
  578. {
  579. TCHAR szTemp[MAX_PATH] = {0};
  580. _tcscpy( szTemp, pszPath );
  581. StripTrailingChar( szTemp, _T('\\') );
  582. DWORD dw = GetFileAttributes( szTemp );
  583. return((dw != 0xFFFFFFFF) && (dw & FILE_ATTRIBUTE_DIRECTORY) );
  584. }