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.

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