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.

1232 lines
33 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: cdoptimp.cpp
  3. *
  4. * Copyright (c) 1998 Microsoft Corporation. All rights reserved.
  5. \**************************************************************************/
  6. #include "precomp.h"
  7. #include "objbase.h"
  8. #include "cdoptimp.h"
  9. #include "cdopti.h"
  10. #include "cddata.h"
  11. extern HINSTANCE g_dllInst;
  12. /////////////
  13. // Typedefs
  14. /////////////
  15. typedef struct Sheet
  16. {
  17. INT iResID;
  18. DLGPROC pfnDlgProc;
  19. }SHEET,*LPSHEET;
  20. typedef struct CDReserved
  21. {
  22. LPCDOPTIONS pCDOpts;
  23. BOOL fChanged;
  24. }CDRESERVED, *LPCDRESERVED;
  25. /////////////
  26. // Defines
  27. /////////////
  28. #define CDKEYSIZE (20)
  29. #define NUMKEYSRC (2)
  30. #define NUMPAGES (3)
  31. //////////
  32. // Globals
  33. //////////
  34. TCHAR gszHelpFile[] = TEXT("deluxcd.hlp");
  35. const TCHAR szCDKeySet[] = TEXT("MSDELXCD");
  36. const TCHAR szCDPlayerPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\DeluxeCD\\Settings");
  37. const TCHAR szCDSysTrayPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
  38. const TCHAR szCDSysTray[] = TEXT("DeluxeCD");
  39. const TCHAR szCDTrayOption[] = TEXT("-tray");
  40. const TCHAR szCDStartPlay[] = TEXT("StartPlay");
  41. const TCHAR szCDExitStop[] = TEXT("ExitStop");
  42. const TCHAR szCDDispMode[] = TEXT("DispMode");
  43. const TCHAR szCDTopMost[] = TEXT("TopMost");
  44. const TCHAR szCDTray[] = TEXT("Tray");
  45. const TCHAR szCDPlayMode[] = TEXT("PlayMode");
  46. const TCHAR szCDIntroTime[] = TEXT("IntroTime");
  47. const TCHAR szCDDownloadEnabled[] = TEXT("DownloadEnabled");
  48. const TCHAR szCDDownloadPrompt[] = TEXT("DownloadPrompt");
  49. const TCHAR szCDBatchEnabled[] = TEXT("BatchEnabled");
  50. const TCHAR szCDByArtist[] = TEXT("ByArtist");
  51. const TCHAR szCDConfirmUpload[] = TEXT("ConfirmUpload");
  52. const TCHAR szCDWindowX[] = TEXT("WindowX");
  53. const TCHAR szCDWindowY[] = TEXT("WindowY");
  54. const TCHAR szCDViewMode[] = TEXT("ViewMode");
  55. const TCHAR szCDCurrentProvider[] = TEXT("CurrentProvider");
  56. const TCHAR szCDProviderPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\DeluxeCD\\Providers\\");
  57. const TCHAR szCDProviderKey[] = TEXT("Provider");
  58. const TCHAR szCDProviderURL[] = TEXT("ProviderURL");
  59. const TCHAR szCDProviderName[] = TEXT("ProviderName");
  60. const TCHAR szCDProviderHome[] = TEXT("ProviderHome");
  61. const TCHAR szCDProviderLogo[] = TEXT("ProviderLogo");
  62. const TCHAR szCDProviderUpload[] = TEXT("ProviderUpload");
  63. ////////////
  64. // IUnknown Implementation for CDOpt
  65. ////////////
  66. CCDOpt::CCDOpt()
  67. {
  68. HRESULT hr;
  69. m_dwRef = 0;
  70. m_pCDData = NULL;
  71. m_pCDOpts = new(CDOPTIONS);
  72. m_hImageList = NULL;
  73. m_pCDTitle = NULL;
  74. m_hInst = NULL;
  75. m_hList = NULL;
  76. m_uDragListMsg = 0L;
  77. m_pfnSubProc = NULL;
  78. m_fEditReturn = FALSE;
  79. m_fVolChanged = FALSE;
  80. m_fAlbumsExpanded = FALSE;
  81. m_fDrivesExpanded = TRUE;
  82. m_pICDNet = FALSE;
  83. m_pCDUploadTitle = NULL;
  84. m_hTitleWnd = NULL;
  85. m_fDelayUpdate = false;
  86. if (m_pCDOpts == NULL)
  87. {
  88. hr = E_OUTOFMEMORY;
  89. }
  90. else
  91. {
  92. memset(m_pCDOpts,0,sizeof(CDOPTIONS));
  93. hr = CreateCDList(&(m_pCDOpts->pCDUnitList));
  94. if (SUCCEEDED(hr))
  95. {
  96. m_pCDOpts->pCDData = new(CDOPTDATA);
  97. if (m_pCDOpts->pCDData == NULL)
  98. {
  99. hr = E_OUTOFMEMORY;
  100. }
  101. else
  102. {
  103. memset(m_pCDOpts->pCDData, 0, sizeof(CDOPTDATA));
  104. hr = GetCDData(m_pCDOpts->pCDData);
  105. if (SUCCEEDED(hr))
  106. {
  107. hr = GetProviderData(m_pCDOpts);
  108. }
  109. }
  110. }
  111. }
  112. if (FAILED(hr))
  113. {
  114. DestroyCDOptions();
  115. }
  116. }
  117. CCDOpt::~CCDOpt()
  118. {
  119. DestroyCDOptions();
  120. }
  121. STDMETHODIMP CCDOpt::QueryInterface(REFIID riid, void** ppv)
  122. {
  123. *ppv = NULL;
  124. if (IID_IUnknown == riid || IID_ICDOpt == riid)
  125. {
  126. *ppv = this;
  127. }
  128. if (NULL==*ppv)
  129. {
  130. return E_NOINTERFACE;
  131. }
  132. AddRef();
  133. return S_OK;
  134. }
  135. STDMETHODIMP_(ULONG) CCDOpt::AddRef(void)
  136. {
  137. return ++m_dwRef;
  138. }
  139. STDMETHODIMP_(ULONG) CCDOpt::Release(void)
  140. {
  141. if (0!=--m_dwRef)
  142. return m_dwRef;
  143. delete this;
  144. return 0;
  145. }
  146. ////////////
  147. // ICDOpt Public Method Implementation
  148. ////////////
  149. STDMETHODIMP_(LPCDOPTIONS) CCDOpt::GetCDOpts(void)
  150. {
  151. return(m_pCDOpts);
  152. }
  153. STDMETHODIMP_(void) CCDOpt::OrderProviders(LPCDPROVIDER *ppProviderList, LPCDPROVIDER pCurrentProvider)
  154. {
  155. if (ppProviderList && *ppProviderList && pCurrentProvider)
  156. {
  157. LPCDPROVIDER pProvider;
  158. LPCDPROVIDER pLast = NULL;
  159. pProvider = *ppProviderList;
  160. while (pProvider)
  161. {
  162. if (pProvider == pCurrentProvider)
  163. {
  164. if (pLast != NULL) // if current is not already head of list
  165. {
  166. pLast->pNext = pProvider->pNext; // Current is now removed from the list
  167. pProvider->pNext = *ppProviderList; // Have current point to head of list
  168. *ppProviderList = pProvider; // Current is now head of list
  169. }
  170. break;
  171. }
  172. pLast = pProvider;
  173. pProvider = pProvider->pNext;
  174. }
  175. }
  176. }
  177. STDMETHODIMP CCDOpt::CreateProviderList(LPCDPROVIDER *ppProviderList)
  178. {
  179. HRESULT hr = S_OK;
  180. if (ppProviderList)
  181. {
  182. LPCDPROVIDER pProvider = m_pCDOpts->pProviderList;
  183. LPCDPROVIDER pCurrentProvider = NULL;
  184. LPCDPROVIDER pNewProvider = NULL;
  185. LPCDPROVIDER pLast = NULL;
  186. while (pProvider)
  187. {
  188. pNewProvider = (LPCDPROVIDER) new(CDPROVIDER);
  189. if (pNewProvider == NULL)
  190. {
  191. hr = E_FAIL;
  192. break;
  193. }
  194. memcpy(pNewProvider, pProvider, sizeof(CDPROVIDER));
  195. pNewProvider->pNext = NULL;
  196. if (pLast)
  197. {
  198. pLast->pNext = pNewProvider;
  199. }
  200. else
  201. {
  202. *ppProviderList = pNewProvider;
  203. }
  204. if (pProvider == m_pCDOpts->pCurrentProvider)
  205. {
  206. pCurrentProvider = pNewProvider;
  207. }
  208. pLast = pNewProvider;
  209. pProvider = pProvider->pNext;
  210. }
  211. if (SUCCEEDED(hr))
  212. {
  213. OrderProviders(ppProviderList, pCurrentProvider);
  214. }
  215. else
  216. {
  217. DestroyProviderList(ppProviderList);
  218. }
  219. }
  220. return(hr);
  221. }
  222. STDMETHODIMP_(void) CCDOpt::DestroyProviderList(LPCDPROVIDER *ppProviderList)
  223. {
  224. if (ppProviderList)
  225. {
  226. while (*ppProviderList)
  227. {
  228. LPCDPROVIDER pTemp = *ppProviderList;
  229. *ppProviderList = (*ppProviderList)->pNext;
  230. delete pTemp;
  231. }
  232. }
  233. }
  234. STDMETHODIMP_(void) CCDOpt::UpdateRegistry(void)
  235. {
  236. if (m_pCDOpts && m_pCDOpts->pCDData)
  237. {
  238. SetCDData(m_pCDOpts->pCDData);
  239. }
  240. }
  241. STDMETHODIMP CCDOpt::OptionsDialog(HWND hWnd, LPCDDATA pCDData, CDOPT_PAGE nStartPage)
  242. {
  243. HRESULT hr = S_OK;
  244. PROPSHEETHEADER psh;
  245. PROPSHEETPAGE psp[NUMPAGES];
  246. int page;
  247. int pages;
  248. TCHAR str[MAX_PATH];
  249. if (m_pCDOpts == NULL)
  250. {
  251. hr = E_INVALIDARG;
  252. }
  253. else
  254. {
  255. LPCDOPTIONS pCDCopy = NULL;
  256. CDRESERVED cdReserved;
  257. cdReserved.pCDOpts = m_pCDOpts;
  258. cdReserved.fChanged = FALSE;
  259. m_pCDOpts->pReserved = (UINT_PTR)&cdReserved;
  260. if (pCDData && SUCCEEDED(pCDData->CheckDatabase(hWnd)))
  261. {
  262. m_pCDData = pCDData;
  263. m_pCDData->AddRef();
  264. }
  265. hr = CopyOptions();
  266. if (SUCCEEDED(hr))
  267. {
  268. pages = NUMPAGES;
  269. if (m_pCDData == NULL)
  270. {
  271. nStartPage = CDOPT_PAGE_PLAY;
  272. pages = 1;
  273. }
  274. for (page = 0; page < pages; page++)
  275. {
  276. memset(&psp[page],0,sizeof(PROPSHEETPAGE));
  277. psp[page].dwSize = sizeof(PROPSHEETPAGE);
  278. psp[page].dwFlags = PSP_DEFAULT;
  279. psp[page].hInstance = g_dllInst;
  280. psp[page].lParam = (LPARAM) this;
  281. switch (page)
  282. {
  283. case 0:
  284. psp[page].pszTemplate = MAKEINTRESOURCE(IDD_CDPLAYEROPTIONS);
  285. psp[page].pfnDlgProc = CCDOpt::PlayerOptionsProc;
  286. break;
  287. case 1:
  288. psp[page].pszTemplate = MAKEINTRESOURCE(IDD_CDTITLEOPTIONS);
  289. psp[page].pfnDlgProc = CCDOpt::TitleOptionsProc;
  290. break;
  291. case 2:
  292. psp[page].pszTemplate = MAKEINTRESOURCE(IDD_CDPLAYLISTS);
  293. psp[page].pfnDlgProc = CCDOpt::PlayListsProc;
  294. break;
  295. }
  296. }
  297. LoadString( g_dllInst, IDS_CDOPTIONS, str, sizeof( str )/sizeof(TCHAR) );
  298. memset(&psh,0,sizeof(psh));
  299. psh.dwSize = sizeof(psh);
  300. psh.dwFlags = PSH_DEFAULT | PSH_PROPSHEETPAGE;
  301. psh.hwndParent = hWnd;
  302. psh.hInstance = g_dllInst;
  303. psh.pszCaption = str;
  304. psh.nPages = pages;
  305. psh.nStartPage = nStartPage;
  306. psh.ppsp = psp;
  307. m_hInst = g_dllInst;
  308. if (PropertySheet(&psh) == -1)
  309. {
  310. hr = E_FAIL; // Big problem.
  311. }
  312. DumpOptionsCopy();
  313. if (SUCCEEDED(hr))
  314. {
  315. if (!cdReserved.fChanged)
  316. {
  317. hr = S_FALSE; // No changes
  318. }
  319. else
  320. {
  321. hr = S_OK; // There have been changes
  322. }
  323. }
  324. }
  325. if (m_pCDData)
  326. {
  327. m_pCDData->Release();
  328. m_pCDData = NULL;
  329. }
  330. }
  331. return(hr);
  332. }
  333. STDMETHODIMP_(void) CCDOpt::DestroyCDOptions(void)
  334. {
  335. if (m_pCDOpts)
  336. {
  337. if (m_pCDOpts->pCDData)
  338. {
  339. delete m_pCDOpts->pCDData;
  340. }
  341. if (m_pCDOpts->pProviderList)
  342. {
  343. DestroyProviderList(&(m_pCDOpts->pProviderList));
  344. }
  345. if (m_pCDOpts->pCDUnitList)
  346. {
  347. DestroyCDList(&(m_pCDOpts->pCDUnitList));
  348. }
  349. delete m_pCDOpts;
  350. }
  351. }
  352. STDMETHODIMP_(void) CCDOpt::RegGetByte(HKEY hKey, const TCHAR *szKey, LPBYTE pByte, BYTE bDefault)
  353. {
  354. DWORD dwSize = sizeof(DWORD);
  355. DWORD dwByte;
  356. if (RegQueryValueEx(hKey, szKey, NULL, NULL, (LPBYTE) &dwByte, &dwSize) != NO_ERROR)
  357. {
  358. *pByte = bDefault;
  359. }
  360. else
  361. {
  362. *pByte = (BYTE) dwByte;
  363. }
  364. }
  365. STDMETHODIMP_(void) CCDOpt::RegGetDWORD(HKEY hKey, const TCHAR *szKey, LPDWORD pdwData, DWORD dwDefault)
  366. {
  367. DWORD dwSize = sizeof(DWORD);
  368. if (RegQueryValueEx(hKey, szKey, NULL, NULL, (LPBYTE) pdwData, &dwSize) != NO_ERROR)
  369. {
  370. *pdwData = dwDefault;
  371. }
  372. }
  373. STDMETHODIMP_(void) CCDOpt::RegSetByte(HKEY hKey, const TCHAR *szKey, BYTE bData)
  374. {
  375. DWORD dwData = (DWORD) bData;
  376. RegSetValueEx( hKey, (LPTSTR) szKey, 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD) );
  377. }
  378. STDMETHODIMP_(void) CCDOpt::RegSetDWORD(HKEY hKey, const TCHAR *szKey, DWORD dwData)
  379. {
  380. RegSetValueEx( hKey, (LPTSTR) szKey, 0, REG_DWORD,(LPBYTE) &dwData, sizeof(DWORD) );
  381. }
  382. STDMETHODIMP_(BOOL) CCDOpt::GetUploadPrompt(void)
  383. {
  384. HKEY hKey;
  385. BOOL fConfirm = CDDEFAULT_CONFIRMUPLOAD;
  386. if (RegOpenKeyEx(HKEY_CURRENT_USER , szCDPlayerPath , 0 , KEY_READ , &hKey) == ERROR_SUCCESS)
  387. {
  388. RegGetByte(hKey, szCDConfirmUpload, (LPBYTE) &fConfirm, CDDEFAULT_CONFIRMUPLOAD);
  389. RegCloseKey(hKey);
  390. }
  391. return fConfirm;
  392. }
  393. STDMETHODIMP_(void) CCDOpt::SetUploadPrompt(BOOL fConfirmUpload)
  394. {
  395. HKEY hKey;
  396. if (RegCreateKeyEx( HKEY_CURRENT_USER, (LPTSTR)szCDPlayerPath, 0, NULL, 0,KEY_WRITE | KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS)
  397. {
  398. RegSetByte(hKey, szCDConfirmUpload, (BYTE) fConfirmUpload);
  399. RegCloseKey(hKey);
  400. }
  401. }
  402. STDMETHODIMP CCDOpt::GetCDData(LPCDOPTDATA pCDData)
  403. {
  404. HRESULT hr = S_OK;
  405. HKEY hKey;
  406. if (pCDData)
  407. {
  408. if (RegOpenKeyEx(HKEY_CURRENT_USER , szCDPlayerPath , 0 , KEY_READ , &hKey) == ERROR_SUCCESS)
  409. {
  410. DWORD dwSize = sizeof(BOOL);
  411. RegGetByte(hKey, szCDStartPlay, (LPBYTE) &pCDData->fStartPlay, CDDEFAULT_START);
  412. RegGetByte(hKey, szCDExitStop, (LPBYTE) &pCDData->fExitStop, CDDEFAULT_EXIT);
  413. RegGetByte(hKey, szCDDispMode, (LPBYTE) &pCDData->fDispMode, CDDEFAULT_DISP);
  414. RegGetByte(hKey, szCDTopMost, (LPBYTE) &pCDData->fTopMost, CDDEFAULT_TOP);
  415. RegGetByte(hKey, szCDTray, (LPBYTE) &pCDData->fTrayEnabled, CDDEFAULT_TRAY);
  416. RegGetDWORD(hKey, szCDIntroTime, (LPDWORD) &pCDData->dwIntroTime, CDDEFAULT_INTRO);
  417. RegGetDWORD(hKey, szCDPlayMode, (LPDWORD) &pCDData->dwPlayMode, CDDEFAULT_PLAY);
  418. RegGetByte(hKey, szCDDownloadEnabled,(LPBYTE) &pCDData->fDownloadEnabled, CDDEFAULT_DOWNLOADENABLED);
  419. RegGetByte(hKey, szCDDownloadPrompt, (LPBYTE) &pCDData->fDownloadPrompt, CDDEFAULT_DOWNLOADPROMPT);
  420. RegGetByte(hKey, szCDBatchEnabled, (LPBYTE) &pCDData->fBatchEnabled, CDDEFAULT_BATCHENABLED);
  421. RegGetByte(hKey, szCDByArtist, (LPBYTE) &pCDData->fByArtist, CDDEFAULT_BYARTIST);
  422. RegGetDWORD(hKey, szCDWindowX, (LPDWORD) &pCDData->dwWindowX, CW_USEDEFAULT);
  423. RegGetDWORD(hKey, szCDWindowY, (LPDWORD) &pCDData->dwWindowY, CW_USEDEFAULT);
  424. RegGetDWORD(hKey, szCDViewMode, (LPDWORD) &pCDData->dwViewMode, 0);
  425. RegCloseKey(hKey);
  426. }
  427. else // Just use the defaults
  428. {
  429. pCDData->fStartPlay = CDDEFAULT_START;
  430. pCDData->fExitStop = CDDEFAULT_EXIT;
  431. pCDData->fDispMode = CDDEFAULT_DISP;
  432. pCDData->fTopMost = CDDEFAULT_TOP;
  433. pCDData->fTrayEnabled = CDDEFAULT_TRAY;
  434. pCDData->dwIntroTime = CDDEFAULT_INTRO;
  435. pCDData->dwPlayMode = CDDEFAULT_PLAY;
  436. pCDData->fDownloadEnabled = CDDEFAULT_DOWNLOADENABLED;
  437. pCDData->fDownloadPrompt = CDDEFAULT_DOWNLOADPROMPT;
  438. pCDData->fBatchEnabled = CDDEFAULT_BATCHENABLED;
  439. pCDData->fByArtist = CDDEFAULT_BYARTIST;
  440. pCDData->dwWindowX = CW_USEDEFAULT ;
  441. pCDData->dwWindowY = CW_USEDEFAULT ;
  442. pCDData->dwViewMode = 0;
  443. }
  444. }
  445. return(hr);
  446. }
  447. STDMETHODIMP CCDOpt::SetCDData(LPCDOPTDATA pCDData)
  448. {
  449. HRESULT hr = E_FAIL;
  450. HKEY hKey;
  451. if (pCDData)
  452. {
  453. if (RegCreateKeyEx( HKEY_CURRENT_USER, (LPTSTR)szCDPlayerPath, 0, NULL, 0,KEY_WRITE | KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS)
  454. {
  455. DWORD dwSize = sizeof(BOOL);
  456. hr = S_OK;
  457. RegSetByte(hKey, szCDStartPlay, (BYTE) pCDData->fStartPlay);
  458. RegSetByte(hKey, szCDExitStop, (BYTE) pCDData->fExitStop);
  459. RegSetByte(hKey, szCDDispMode, (BYTE) pCDData->fDispMode);
  460. RegSetByte(hKey, szCDTopMost, (BYTE) pCDData->fTopMost);
  461. RegSetByte(hKey, szCDTray, (BYTE) pCDData->fTrayEnabled);
  462. RegSetDWORD(hKey, szCDIntroTime, (DWORD) pCDData->dwIntroTime);
  463. RegSetDWORD(hKey, szCDPlayMode, (DWORD) pCDData->dwPlayMode);
  464. RegSetByte(hKey, szCDDownloadEnabled,(BYTE) pCDData->fDownloadEnabled);
  465. RegSetByte(hKey, szCDDownloadPrompt, (BYTE) pCDData->fDownloadPrompt);
  466. RegSetByte(hKey, szCDBatchEnabled, (BYTE) pCDData->fBatchEnabled);
  467. RegSetByte(hKey, szCDByArtist, (BYTE) pCDData->fByArtist);
  468. RegSetDWORD(hKey, szCDWindowX, (DWORD) pCDData->dwWindowX);
  469. RegSetDWORD(hKey, szCDWindowY, (DWORD) pCDData->dwWindowY);
  470. RegSetDWORD(hKey, szCDViewMode, (DWORD) pCDData->dwViewMode);
  471. RegCloseKey(hKey);
  472. if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, (LPTSTR)szCDSysTrayPath, 0, NULL, 0,KEY_WRITE | KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS)
  473. {
  474. TCHAR szPath[MAX_PATH];
  475. TCHAR szCommand[MAX_PATH + 5];
  476. if (pCDData->fTrayEnabled)
  477. {
  478. GetModuleFileName(NULL, szPath, sizeof(szPath)/sizeof(TCHAR));
  479. wsprintf(szCommand, TEXT("%s %s"), szPath, szCDTrayOption);
  480. RegSetValueEx( hKey, (LPTSTR) szCDSysTray, 0, REG_SZ,(LPBYTE) szCommand, (wcslen(szCommand)*sizeof(TCHAR))+sizeof(TCHAR));
  481. }
  482. else
  483. {
  484. RegDeleteValue( hKey, (LPTSTR) szCDSysTray);
  485. }
  486. RegCloseKey(hKey);
  487. }
  488. }
  489. }
  490. return(hr);
  491. }
  492. STDMETHODIMP_(void) CCDOpt::GetCurrentProviderURL(TCHAR *szProviderURL)
  493. {
  494. HKEY hKey;
  495. if (szProviderURL)
  496. {
  497. if (RegOpenKeyEx(HKEY_CURRENT_USER , szCDPlayerPath , 0 , KEY_READ , &hKey) == ERROR_SUCCESS)
  498. {
  499. DWORD dwSize = MAX_PATH;
  500. RegQueryValueEx(hKey, szCDCurrentProvider, NULL, NULL, (LPBYTE) szProviderURL, &dwSize);
  501. RegCloseKey(hKey);
  502. }
  503. }
  504. }
  505. STDMETHODIMP CCDOpt::GetProviderData(LPCDOPTIONS pCDOpts)
  506. {
  507. HRESULT hr = S_OK;
  508. DWORD dwCount = 0;
  509. TCHAR szPath[MAX_PATH];
  510. BOOL done = FALSE;
  511. LPCDPROVIDER pProvider;
  512. LPCDPROVIDER *ppLast;
  513. HKEY hKey;
  514. TCHAR szProviderURL[MAX_PATH];
  515. if (pCDOpts)
  516. {
  517. szProviderURL[0] = TEXT('\0');
  518. GetCurrentProviderURL(szProviderURL);
  519. ppLast = &(pCDOpts->pProviderList);
  520. while (!done)
  521. {
  522. wsprintf(szPath,TEXT("%s%s%04d"), szCDProviderPath, szCDProviderKey, dwCount);
  523. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE , szPath , 0 , KEY_READ , &hKey) == ERROR_SUCCESS)
  524. {
  525. BOOL fGotIt = FALSE;
  526. pProvider = new (CDPROVIDER);
  527. if (pProvider == NULL)
  528. {
  529. hr = E_OUTOFMEMORY;
  530. done = TRUE;
  531. }
  532. else
  533. {
  534. memset(pProvider, 0, sizeof(CDPROVIDER));
  535. DWORD cbSize = sizeof(pProvider->szProviderURL);
  536. if (RegQueryValueEx(hKey, szCDProviderURL, NULL, NULL, (LPBYTE) pProvider->szProviderURL, &cbSize) == NO_ERROR)
  537. {
  538. cbSize = sizeof(pProvider->szProviderName);
  539. if (RegQueryValueEx(hKey, szCDProviderName, NULL, NULL, (LPBYTE) pProvider->szProviderName, &cbSize) == NO_ERROR)
  540. {
  541. cbSize = sizeof(pProvider->szProviderHome);
  542. if (RegQueryValueEx(hKey, szCDProviderHome, NULL, NULL, (LPBYTE) pProvider->szProviderHome, &cbSize) == NO_ERROR)
  543. {
  544. TCHAR szTempLogo[MAX_PATH];
  545. cbSize = sizeof(szTempLogo);
  546. if (RegQueryValueEx(hKey, szCDProviderLogo, NULL, NULL, (LPBYTE) szTempLogo, &cbSize) == NO_ERROR)
  547. {
  548. ExpandEnvironmentStrings(szTempLogo,pProvider->szProviderLogo,sizeof(pProvider->szProviderLogo)/sizeof(TCHAR));
  549. cbSize = sizeof(pProvider->szProviderUpload);
  550. RegQueryValueEx(hKey, szCDProviderUpload, NULL, NULL, (LPBYTE) pProvider->szProviderUpload, &cbSize);
  551. *ppLast = pProvider;
  552. ppLast = &(pProvider)->pNext;
  553. fGotIt = TRUE;
  554. if (pCDOpts->pDefaultProvider == NULL)
  555. {
  556. pCDOpts->pDefaultProvider = pProvider;
  557. pCDOpts->pCurrentProvider = pProvider;
  558. }
  559. if (!lstrcmp(szProviderURL, pProvider->szProviderURL))
  560. {
  561. pCDOpts->pCurrentProvider = pProvider;
  562. }
  563. #ifdef DEBUG
  564. char szCert[255];
  565. CreateProviderKey(pProvider, szCert, sizeof(szCert));
  566. char szOut[255];
  567. wsprintf(szOut,"%s = %s, Verify = %d\n", pProvider->szProviderName, szCert, VerifyProvider(pProvider, szCert));
  568. OutputDebugString(szOut);
  569. #endif
  570. }
  571. }
  572. }
  573. }
  574. if (!fGotIt)
  575. {
  576. delete pProvider;
  577. pProvider = NULL;
  578. }
  579. }
  580. RegCloseKey(hKey);
  581. dwCount++;
  582. }
  583. else
  584. {
  585. done = TRUE;
  586. }
  587. }
  588. }
  589. return(hr);
  590. }
  591. STDMETHODIMP CCDOpt::SetProviderData(LPCDOPTIONS pCDOpts)
  592. {
  593. HRESULT hr = S_OK;
  594. DWORD dwCount = 0;
  595. BOOL done = FALSE;
  596. LPCDPROVIDER pProvider;
  597. HKEY hKey;
  598. pProvider = pCDOpts->pCurrentProvider;
  599. if (pProvider)
  600. {
  601. if (RegCreateKeyEx( HKEY_CURRENT_USER, (LPTSTR)szCDPlayerPath, 0, NULL, 0,KEY_WRITE | KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS)
  602. {
  603. RegSetValueEx( hKey, (LPTSTR) szCDCurrentProvider, 0, REG_SZ, (LPBYTE) pProvider->szProviderURL, (lstrlen(pProvider->szProviderURL)*sizeof(TCHAR))+sizeof(TCHAR));
  604. RegCloseKey(hKey);
  605. }
  606. }
  607. return(hr);
  608. }
  609. STDMETHODIMP_(void) CCDOpt::DumpOptionsCopy(void)
  610. {
  611. if (m_pCDCopy)
  612. {
  613. if (m_pCDCopy->pCDData)
  614. {
  615. delete m_pCDCopy->pCDData;
  616. }
  617. delete m_pCDCopy;
  618. m_pCDCopy = NULL;
  619. }
  620. }
  621. STDMETHODIMP CCDOpt::CopyOptions(void)
  622. {
  623. HRESULT hr = S_OK;
  624. if (m_pCDOpts)
  625. {
  626. m_pCDCopy = (LPCDOPTIONS) new(CDOPTIONS);
  627. if (m_pCDCopy == NULL)
  628. {
  629. hr = E_OUTOFMEMORY;
  630. }
  631. else
  632. {
  633. memcpy(m_pCDCopy, m_pCDOpts, sizeof(CDOPTIONS));
  634. m_pCDCopy->pCDData = new (CDOPTDATA);
  635. if (m_pCDCopy->pCDData == NULL)
  636. {
  637. hr = E_OUTOFMEMORY;
  638. }
  639. else
  640. {
  641. memcpy(m_pCDCopy->pCDData, m_pCDOpts->pCDData, sizeof(CDOPTDATA));
  642. }
  643. }
  644. }
  645. if (FAILED(hr))
  646. {
  647. DumpOptionsCopy();
  648. }
  649. return(hr);
  650. }
  651. STDMETHODIMP_(BOOL) CCDOpt::OptionsChanged(LPCDOPTIONS pCDOpts)
  652. {
  653. BOOL fChanged = FALSE;
  654. if (pCDOpts)
  655. {
  656. LPCDRESERVED pCDReserved = (LPCDRESERVED) pCDOpts->pReserved;
  657. LPCDOPTIONS pCDOriginal = pCDReserved->pCDOpts;
  658. fChanged = m_fVolChanged;
  659. if (!fChanged)
  660. {
  661. if (memcmp(pCDOpts->pCDData,pCDOriginal->pCDData,sizeof(CDOPTDATA)))
  662. {
  663. fChanged = TRUE;
  664. }
  665. else if (pCDOpts->pCurrentProvider != pCDOriginal->pCurrentProvider)
  666. {
  667. fChanged = TRUE;
  668. }
  669. else if (m_pCDData)
  670. {
  671. LPCDTITLE pCDTitle = m_pCDData->GetTitleList();
  672. while (pCDTitle)
  673. {
  674. if (pCDTitle->fChanged || pCDTitle->fRemove)
  675. {
  676. fChanged = TRUE;
  677. break;
  678. }
  679. pCDTitle = pCDTitle->pNext;
  680. }
  681. }
  682. }
  683. }
  684. return(fChanged);
  685. }
  686. STDMETHODIMP_(void) CCDOpt::ApplyCurrentSettings(void)
  687. {
  688. if (m_pCDCopy)
  689. {
  690. if (OptionsChanged(m_pCDCopy))
  691. {
  692. LPCDRESERVED pCDReserved = (LPCDRESERVED) m_pCDCopy->pReserved;
  693. pCDReserved->fChanged = TRUE;
  694. memcpy(m_pCDOpts->pCDData, m_pCDCopy->pCDData, sizeof(CDOPTDATA));
  695. m_pCDOpts->pCurrentProvider = m_pCDCopy->pCurrentProvider;
  696. SetCDData(m_pCDCopy->pCDData);
  697. SetProviderData(m_pCDCopy);
  698. if (m_pCDData)
  699. {
  700. m_pCDData->PersistTitles();
  701. }
  702. if (m_pCDCopy->pfnOptionsCallback)
  703. {
  704. m_pCDCopy->pfnOptionsCallback(m_pCDCopy);
  705. }
  706. }
  707. }
  708. }
  709. STDMETHODIMP_(void) CCDOpt::ToggleApplyButton(HWND hDlg)
  710. {
  711. HWND hwndSheet;
  712. if (m_pCDCopy)
  713. {
  714. hwndSheet = GetParent(hDlg);
  715. if (OptionsChanged(m_pCDCopy))
  716. {
  717. PropSheet_Changed(hwndSheet,hDlg);
  718. }
  719. else
  720. {
  721. PropSheet_UnChanged(hwndSheet,hDlg);
  722. }
  723. }
  724. }
  725. STDMETHODIMP CCDOpt::AcquireKey(LPCDKEY pCDKey, char *szName)
  726. {
  727. HRESULT hr = E_FAIL;
  728. DWORD dwLength = strlen(szName);
  729. pCDKey->hProv = NULL;
  730. if(!CryptAcquireContext(&(pCDKey->hProv), szCDKeySet, NULL, PROV_RSA_FULL, 0 ))
  731. {
  732. hr = GetLastError();
  733. if (hr == NTE_BAD_KEYSET)
  734. {
  735. if(CryptAcquireContext(&(pCDKey->hProv), szCDKeySet, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET ))
  736. {
  737. hr = S_OK;
  738. }
  739. else
  740. {
  741. hr = GetLastError();
  742. }
  743. }
  744. }
  745. if(pCDKey->hProv)
  746. {
  747. if(CryptCreateHash(pCDKey->hProv, CALG_MD5, 0, 0, &(pCDKey->hHash)))
  748. {
  749. if(CryptHashData(pCDKey->hHash, (BYTE *)szName, dwLength, 0))
  750. {
  751. if(CryptDeriveKey(pCDKey->hProv, CALG_RC2, pCDKey->hHash, CRYPT_EXPORTABLE, &(pCDKey->hKey)))
  752. {
  753. hr = S_OK;
  754. }
  755. }
  756. }
  757. }
  758. if (FAILED(hr))
  759. {
  760. hr = GetLastError();
  761. }
  762. return(hr);
  763. }
  764. STDMETHODIMP_(void) CCDOpt::ReleaseKey(LPCDKEY pCDKey)
  765. {
  766. if(pCDKey->hHash)
  767. {
  768. CryptDestroyHash(pCDKey->hHash);
  769. pCDKey->hHash = 0;
  770. }
  771. if(pCDKey->hKey)
  772. {
  773. CryptDestroyKey(pCDKey->hKey);
  774. pCDKey->hKey = 0;
  775. }
  776. if(pCDKey->hProv)
  777. {
  778. CryptReleaseContext(pCDKey->hProv, 0);
  779. pCDKey->hProv = 0;
  780. }
  781. }
  782. // This function takes a certification key, decrypts it and determines it's validity
  783. //
  784. // It first converts the returned data from it's re-able numeric text version, into
  785. // it's raw encrypted data format.
  786. //
  787. // It then generates the data key using the current provider data, as was done when the key
  788. // was generated
  789. //
  790. // It then decrypts the encrypted data and compares it to the data key, if they match, great
  791. // if not, then this provider is not certified and was attempting to mess with us.
  792. STDMETHODIMP_(BOOL) CCDOpt::VerifyProvider(LPCDPROVIDER pCDProvider, TCHAR *szCertKey)
  793. {
  794. BOOL fCertified = FALSE;
  795. CDKEY cdKey;
  796. char szKey[CDKEYSIZE * 2]; //note: crypto doesn't know unicode, we'll do the conversion later
  797. TCHAR szMatch[CDKEYSIZE];
  798. DWORD dwSize;
  799. TCHAR *szSrc;
  800. TCHAR szHex[3];
  801. LPBYTE pData;
  802. HRESULT hr;
  803. szSrc = szCertKey;
  804. dwSize = lstrlen(szCertKey);
  805. szHex[2] = TEXT('\0');
  806. pData = (LPBYTE) szKey;
  807. for (DWORD dwPos = 0; dwPos < dwSize; dwPos += 2)
  808. {
  809. szHex[0] = szSrc[0];
  810. szHex[1] = szSrc[1];
  811. szSrc += 2;
  812. _stscanf(szHex,TEXT("%xd"),pData);
  813. pData++;
  814. }
  815. dwSize = dwSize >> 1;
  816. memset(&cdKey,0,sizeof(cdKey));
  817. if (SUCCEEDED(CreateCertString(pCDProvider, szMatch)))
  818. {
  819. char chKeyName[MAX_PATH];
  820. #ifdef UNICODE
  821. WideCharToMultiByte(CP_ACP, 0, pCDProvider->szProviderName,
  822. -1, chKeyName, MAX_PATH, NULL, NULL);
  823. #else
  824. strcpy(chKeyName,pCDProvider->szProviderName);
  825. #endif
  826. hr = AcquireKey(&cdKey, chKeyName);
  827. if (SUCCEEDED(hr))
  828. {
  829. if (CryptDecrypt(cdKey.hKey, 0, TRUE, 0, (BYTE *) szKey, &dwSize))
  830. {
  831. szKey[dwSize] = TEXT('\0');
  832. //convert key back to unicode for string comparison
  833. #ifdef UNICODE
  834. wchar_t wszKey[CDKEYSIZE*2];
  835. MultiByteToWideChar( CP_ACP, 0, szKey, -1, wszKey, sizeof(wszKey) / sizeof(wchar_t) );
  836. #else
  837. char wszKey[CDKEYSIZE*2];
  838. strcpy(wszKey,szKey);
  839. #endif
  840. if (lstrcmp(szMatch, wszKey) == 0)
  841. {
  842. fCertified = TRUE;
  843. }
  844. }
  845. else
  846. {
  847. hr = GetLastError();
  848. if (hr == NTE_PERM)
  849. {
  850. //succeed in the case where crypto fails due to import restrictions (i.e. France)
  851. fCertified = TRUE;
  852. }
  853. }
  854. ReleaseKey(&cdKey);
  855. }
  856. }
  857. return fCertified;
  858. }
  859. // This function creates a string to be encrypted based on data in the provider header
  860. //
  861. // It takes the provider name and the provider URL and strips out any spaces and punctuation
  862. // Of the data that remains, it only uses every other character. It fills out the key
  863. // to exactly CDKEYSIZE characters, when it's full it stops, if it runs out of input
  864. // characters from the header, it simply wraps back to the begining of the input data until full.
  865. // Also, the output characters are stored in reverse order than they are found and every other
  866. // character is capitalized, while all others are lowercased.
  867. // This generates a key that is encrypted using crypto.
  868. //
  869. // During runtime in the shipped product, the key passed down to us is decrypted, this key is
  870. // re-generated from the provider and the strings must match, if not, well, then it's not certified.
  871. //
  872. STDMETHODIMP CCDOpt::CreateCertString(LPCDPROVIDER pCDProvider, TCHAR *szCertStr)
  873. {
  874. HRESULT hr = S_OK;
  875. TCHAR *pDest = szCertStr + (CDKEYSIZE - 2);
  876. TCHAR *pSrc = NULL;
  877. TCHAR *pSrcPtrs[NUMKEYSRC];
  878. DWORD count = 0;
  879. DWORD dwSrc = 0;
  880. pSrcPtrs[0] = pCDProvider->szProviderName;
  881. pSrcPtrs[1] = pCDProvider->szProviderURL;
  882. pSrc = pSrcPtrs[dwSrc];
  883. while(count < (DWORD)(CDKEYSIZE - 1))
  884. {
  885. while(*pSrc && (_istspace(*pSrc) || _istpunct(*pSrc)))
  886. {
  887. pSrc++;
  888. }
  889. if (*pSrc == TEXT('\0'))
  890. {
  891. dwSrc = (dwSrc + 1) % NUMKEYSRC;
  892. if (dwSrc == 0 && count == 0)
  893. {
  894. hr = E_INVALIDARG;
  895. break;
  896. }
  897. pSrc = pSrcPtrs[dwSrc];
  898. }
  899. else
  900. {
  901. *pDest = *pSrc++;
  902. if (*pSrc != TEXT('\0'))
  903. {
  904. pSrc++;
  905. }
  906. if (count & 1)
  907. {
  908. *pDest = _totlower(*pDest);
  909. }
  910. else
  911. {
  912. *pDest = _totupper(*pDest);
  913. }
  914. *pDest--;
  915. count++;
  916. }
  917. }
  918. if (SUCCEEDED(hr))
  919. {
  920. szCertStr[CDKEYSIZE - 1] = TEXT('\0');
  921. }
  922. return(hr);
  923. }
  924. // This function will generate an Certification string using the provider information,
  925. //
  926. // this function only operates in a build that has DEBUG defined, in the shipping version this
  927. // function will return E_NOTIMPL.
  928. //
  929. // First, using the provider data, a data key is generated of a precise size. This key is then
  930. // encrypted. The raw encrypted data is then converted to a readable numeric text format and
  931. // returned as the certification key for this provider
  932. //
  933. // This certification key will be provided to the provided who will download it upon request to
  934. // allow us to verify that they are indeed a licensed cd data provider.
  935. //
  936. // This key does NOT expire, it's mainly here to prevent unlicensed data providers from hooking
  937. // into this product.
  938. STDMETHODIMP CCDOpt::CreateProviderKey(LPCDPROVIDER pCDProvider, TCHAR *szCertKey, UINT cBytes)
  939. {
  940. HRESULT hr = E_NOTIMPL;
  941. #ifdef DEBUG
  942. hr = S_OK;
  943. if (cBytes < 128 || pCDProvider == NULL || szCertKey == NULL)
  944. {
  945. hr = E_INVALIDARG;
  946. }
  947. else
  948. {
  949. TCHAR szKey[CDKEYSIZE * 2];
  950. if (SUCCEEDED(CreateCertString(pCDProvider, szKey)))
  951. {
  952. CDKEY cdKey;
  953. memset(&cdKey,0,sizeof(cdKey));
  954. hr = AcquireKey(&cdKey, pCDProvider->szProviderName);
  955. if (SUCCEEDED(hr))
  956. {
  957. DWORD dwSize = lstrlen(szKey);
  958. if (CryptEncrypt(cdKey.hKey, 0, TRUE, 0, (BYTE *) szKey, &dwSize, CDKEYSIZE * 2))
  959. {
  960. LPBYTE pData = (LPBYTE) szKey;
  961. TCHAR *szDest = szCertKey;
  962. for (DWORD dwPos = 0; dwPos < dwSize; dwPos++, szDest += 2, pData++)
  963. {
  964. wsprintf(szDest, TEXT("%02x"), (UINT) *pData);
  965. }
  966. hr = S_OK;
  967. }
  968. else
  969. {
  970. hr = GetLastError();
  971. }
  972. ReleaseKey(&cdKey);
  973. }
  974. }
  975. }
  976. #endif // DEBUG
  977. return hr;
  978. }
  979.