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.

2753 lines
71 KiB

  1. //--------------------------------------------------------------------------;
  2. //
  3. // File: cddb.cpp
  4. //
  5. // Copyright (c) 1998 Microsoft Corporation. All rights reserved
  6. //
  7. //--------------------------------------------------------------------------;
  8. #include "precomp.h"
  9. #include "cdopti.h"
  10. #include "cddata.h"
  11. #include "shlobj.h"
  12. #include "shlwapi.h"
  13. #define SECTION_BUFFER (512)
  14. #define PLAYLIST_BUFFER (255)
  15. #define BUFFERINC (128)
  16. #define MAXNUMPLAY (127)
  17. #define ROWSET 1
  18. #ifndef SQL_SUCCEEDED
  19. #define SQL_SUCCEEDED(rc) (((rc)&(~1))==0)
  20. #endif
  21. #ifndef SQL_W_CHAR
  22. #undef SQL_C_WCHAR
  23. #define SQL_C_WCHAR (-8)
  24. #endif
  25. #ifndef SQL_LONGCHAR_FIELD
  26. #define SQL_LONGCHAR_FIELD (-10)
  27. #endif
  28. const TCHAR gszIniFile[] = TEXT("cdplayer.ini");
  29. const TCHAR gszDefault[] = TEXT("\0");
  30. const TCHAR gszArtist[] = TEXT("artist");
  31. const TCHAR gszTitle[] = TEXT("title");
  32. const TCHAR gszNumTracks[] = TEXT("numtracks");
  33. const TCHAR gszOrder[] = TEXT("order");
  34. const TCHAR gszNumPlay[] = TEXT("numplay");
  35. const TCHAR gszDriverName[] = TEXT("Microsoft Access Driver (*.mdb)");
  36. const TCHAR gszDSNAttr[] = TEXT("DSN=DeluxeCD%cDefaultDir=%s%cDriverID=25%cDBQ=DeluxeCD.mdb%c");
  37. const TCHAR gszDSNCreate[] = TEXT("CREATE_DB=%s\\DeluxeCD.mdb%c");
  38. const TCHAR gszTitleTable[] = TEXT("Titles");
  39. const TCHAR gszTrackTable[] = TEXT("Tracks");
  40. const TCHAR gszMenuTable[] = TEXT("Menus");
  41. const TCHAR gszBatchTable[] = TEXT("Batch");
  42. TCHAR gszDSN[] = TEXT("DeluxeCD");
  43. TCHAR gszTitlesCreate[] = TEXT("create table Titles ")
  44. TEXT("(")
  45. TEXT("TitleID long, ")
  46. TEXT("Artist longchar, ")
  47. TEXT("Title longchar, ")
  48. TEXT("Copyright longchar, ")
  49. TEXT("Label longchar, ")
  50. TEXT("ReleaseDate longchar, ")
  51. TEXT("NumTracks long, ")
  52. TEXT("NumMenus long, ")
  53. TEXT("PlayList longchar, ")
  54. TEXT("TitleQuery longchar ")
  55. TEXT(")");
  56. TCHAR gszTracksCreate[] = TEXT("create table Tracks ")
  57. TEXT("(")
  58. TEXT("TitleID long, ")
  59. TEXT("TrackID long, ")
  60. TEXT("TrackName longchar ")
  61. TEXT(")");
  62. TCHAR gszMenusCreate[] = TEXT("create table Menus ")
  63. TEXT("(")
  64. TEXT("TitleID long, ")
  65. TEXT("MenuID long, ")
  66. TEXT("MenuName longchar, ")
  67. TEXT("MenuQuery longchar ")
  68. TEXT(")");
  69. TCHAR gszBatchCreate[] = TEXT("create table Batch ")
  70. TEXT("(")
  71. TEXT("TitleID long, ")
  72. TEXT("NumTracks long, ")
  73. TEXT("TitleQuery longchar")
  74. TEXT(")");
  75. SDWORD gcbTitles[] = { 0, SQL_NTS, SQL_NTS, SQL_NTS, SQL_NTS, SQL_NTS, 0, 0, SQL_NTS, INTERNET_MAX_PATH_LENGTH };
  76. SDWORD gcbTracks[] = { 0, 0, SQL_NTS };
  77. SDWORD gcbMenus[] = { 0, 0, SQL_NTS, INTERNET_MAX_PATH_LENGTH };
  78. SDWORD gcbBatch[] = { 0, 0, INTERNET_MAX_PATH_LENGTH };
  79. extern HINSTANCE g_dllInst;
  80. ////////////
  81. // Functions
  82. ////////////
  83. CCDData::CCDData()
  84. {
  85. m_pTitleList = NULL;
  86. m_pBatchList = NULL;
  87. m_dwLoadCnt = 0;
  88. m_dwBatchCnt = 0;
  89. m_henv = NULL;
  90. m_hdbc = NULL;
  91. m_fToldUser = FALSE;
  92. m_pSQL = NULL;
  93. m_dwRef = 0;
  94. memset(&m_bd, 0, sizeof(m_bd));
  95. InitializeCriticalSection(&m_crit);
  96. }
  97. CCDData::~CCDData()
  98. {
  99. CloseDatabase();
  100. if (m_pTitleList)
  101. {
  102. DestroyTitles(&m_pTitleList);
  103. }
  104. if (m_pSQL)
  105. {
  106. delete m_pSQL;
  107. }
  108. DeleteCriticalSection(&m_crit);
  109. }
  110. STDMETHODIMP CCDData::QueryInterface(REFIID riid, void** ppv)
  111. {
  112. *ppv = NULL;
  113. if (IID_IUnknown == riid || IID_ICDData == riid)
  114. {
  115. *ppv = this;
  116. }
  117. if (NULL==*ppv)
  118. {
  119. return E_NOINTERFACE;
  120. }
  121. AddRef();
  122. return S_OK;
  123. }
  124. STDMETHODIMP CCDData::GetSQLPtr(BOOL fInited)
  125. {
  126. HRESULT hr = S_OK;
  127. if (m_pSQL == NULL)
  128. {
  129. static BOOL fAttempt = FALSE;
  130. if (!fAttempt)
  131. {
  132. m_pSQL = new SQL;
  133. if (m_pSQL && !m_pSQL->Initialize())
  134. {
  135. delete m_pSQL;
  136. m_pSQL = NULL;
  137. hr = E_FAIL;
  138. }
  139. else
  140. {
  141. if (!fInited) // we must be running in shell mode, quietly initialize
  142. {
  143. Initialize(NULL);
  144. CheckDatabase(NULL);
  145. }
  146. }
  147. }
  148. else
  149. {
  150. hr = E_FAIL;
  151. }
  152. fAttempt = TRUE;
  153. }
  154. return(hr);
  155. }
  156. STDMETHODIMP_(ULONG) CCDData::AddRef(void)
  157. {
  158. return ++m_dwRef;
  159. }
  160. STDMETHODIMP_(ULONG) CCDData::Release(void)
  161. {
  162. if (0!=--m_dwRef)
  163. return m_dwRef;
  164. delete this;
  165. return 0;
  166. }
  167. STDMETHODIMP_(void) CCDData::Enter(void)
  168. {
  169. EnterCriticalSection(&m_crit);
  170. }
  171. STDMETHODIMP_(void) CCDData::Leave(void)
  172. {
  173. LeaveCriticalSection(&m_crit);
  174. }
  175. STDMETHODIMP CCDData::GetUnknownString(TCHAR **ppStr, const TCHAR *szSection, const TCHAR *szEntry, DWORD dwInitialAlloc)
  176. {
  177. TCHAR *pStr;
  178. DWORD dwSize;
  179. DWORD dwResult;
  180. HRESULT hr = S_OK;
  181. dwSize = dwInitialAlloc - BUFFERINC;
  182. pStr = NULL;
  183. do
  184. {
  185. dwSize += BUFFERINC;
  186. if (pStr)
  187. {
  188. delete pStr;
  189. }
  190. pStr = new(TCHAR[dwSize]);
  191. if (pStr == NULL)
  192. {
  193. hr = E_OUTOFMEMORY;
  194. break;
  195. }
  196. dwResult = GetPrivateProfileString(szSection, szEntry, TEXT("\0"), pStr, dwSize, gszIniFile);
  197. }
  198. while (dwResult == (dwSize - 2));
  199. *ppStr = pStr;
  200. return(hr);
  201. }
  202. STDMETHODIMP_(void) CCDData::ImportTrack(TCHAR *szDiscID, DWORD dwTrack)
  203. {
  204. TCHAR szTrack[6];
  205. wsprintf(szTrack,TEXT("%d"),dwTrack);
  206. GetPrivateProfileString(szDiscID,szTrack,gszDefault,m_bd.CDTrack.szName,CDSTR,gszIniFile);
  207. }
  208. STDMETHODIMP_(RETCODE) CCDData::ImportTracks(HSTMT hstmt, TCHAR *szDiscID)
  209. {
  210. RETCODE rc = SQL_SUCCESS;
  211. for (DWORD dwTrack = 0; dwTrack < m_bd.CDTitle.dwNumTracks; dwTrack++)
  212. {
  213. ImportTrack(szDiscID, dwTrack);
  214. rc = m_pSQL->SetPos(hstmt, 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  215. if (rc == SQL_SUCCESS)
  216. {
  217. m_bd.dwTrackID++;
  218. }
  219. else
  220. {
  221. ReportError(&m_bd, hstmt);
  222. break;
  223. }
  224. }
  225. return(rc);
  226. }
  227. STDMETHODIMP CCDData::ImportTitle(TCHAR *szDiscID)
  228. {
  229. HRESULT hr = S_OK;
  230. DWORD dwTitleID;
  231. _stscanf(szDiscID,TEXT("%xd"),&dwTitleID);
  232. if (dwTitleID == CDTITLE_NODISC)
  233. {
  234. hr = E_INVALIDARG;
  235. }
  236. else
  237. {
  238. m_bd.CDTitle.dwTitleID = dwTitleID;
  239. m_bd.CDTitle.dwNumTracks = GetPrivateProfileInt(szDiscID,gszNumTracks,0,gszIniFile);
  240. m_bd.CDTitle.dwNumPlay = GetPrivateProfileInt(szDiscID,gszNumPlay,0,gszIniFile);
  241. GetPrivateProfileString(szDiscID, gszArtist, gszDefault, m_bd.CDTitle.szArtist, CDSTR, gszIniFile);
  242. GetPrivateProfileString(szDiscID, gszTitle, gszDefault, m_bd.CDTitle.szTitle, CDSTR, gszIniFile);
  243. m_bd.szPlayList[0] = TEXT('\0');
  244. m_bd.szQuery[0] = TEXT('\0');
  245. if (m_bd.CDTitle.dwNumPlay)
  246. {
  247. TCHAR *pPlayTable = NULL;
  248. TCHAR *pText = NULL;
  249. DWORD dwIndex;
  250. int iNum;
  251. TCHAR *pDst = m_bd.szPlayList;
  252. m_bd.CDTitle.dwNumPlay = min(m_bd.CDTitle.dwNumPlay, MAXNUMPLAY);
  253. if (FAILED(GetUnknownString(&pPlayTable, szDiscID, gszOrder, PLAYLIST_BUFFER)))
  254. {
  255. m_bd.CDTitle.dwNumPlay = 0;
  256. }
  257. else
  258. {
  259. pText = pPlayTable;
  260. for (dwIndex = 0; dwIndex < m_bd.CDTitle.dwNumPlay && *pText; dwIndex++)
  261. {
  262. _stscanf(pText,TEXT("%d"), &iNum);
  263. wsprintf(pDst, TEXT("%02x"), iNum);
  264. while(*pDst != TEXT('\0'))
  265. {
  266. pDst++;
  267. }
  268. while(isdigit(*pText++));
  269. }
  270. delete pPlayTable;
  271. }
  272. }
  273. }
  274. return(hr);
  275. }
  276. STDMETHODIMP_(void) CCDData::ImportDatabase(LPTIMEDMETER ptm, HSTMT *hstmt, TCHAR *szDiscID)
  277. {
  278. DWORD dwCount = 0;
  279. RETCODE rc;
  280. while(*szDiscID)
  281. {
  282. m_bd.dwTrackID = 0;
  283. m_bd.dwMenuID = 0;
  284. if (SUCCEEDED(ImportTitle(szDiscID)))
  285. {
  286. rc = ImportTracks(hstmt[1], szDiscID);
  287. if (rc == SQL_SUCCESS)
  288. {
  289. rc = m_pSQL->SetPos(hstmt[0], 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  290. ReportError(&m_bd, hstmt);
  291. }
  292. if (!SQL_SUCCEEDED(rc))
  293. {
  294. break;
  295. }
  296. }
  297. UpdateMeter(ptm);
  298. while(*szDiscID++);
  299. }
  300. }
  301. STDMETHODIMP_(DWORD) CCDData::ImportCount(TCHAR *pEntries)
  302. {
  303. TCHAR *szDiscID = pEntries;
  304. DWORD dwCount = 0;
  305. while(*szDiscID)
  306. {
  307. dwCount++;
  308. while(*szDiscID++);
  309. }
  310. return(dwCount);
  311. }
  312. STDMETHODIMP_(void) CCDData::CreateMeter(LPTIMEDMETER ptm, HWND hWnd, DWORD dwCount, DWORD dwJump, UINT uStringID)
  313. {
  314. if (hWnd && ptm)
  315. {
  316. ptm->hMeter = CreateDialog(g_dllInst,MAKEINTRESOURCE(IDD_LOADSTATUS),hWnd, MeterHandler);
  317. if (ptm->hMeter)
  318. {
  319. ptm->hParent = hWnd;
  320. ptm->dwStartTime = timeGetTime();
  321. ptm->dwRange = dwCount;
  322. ptm->fShowing = FALSE;
  323. ptm->dwCount = 0;
  324. ptm->dwShowCount = 0;
  325. ptm->dwJump = dwJump;
  326. if (uStringID != 0)
  327. {
  328. TCHAR szTitle[255];
  329. LoadString(g_dllInst, uStringID, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  330. SetWindowText(ptm->hMeter, szTitle);
  331. }
  332. }
  333. }
  334. else
  335. {
  336. if (ptm)
  337. {
  338. memset(ptm, 0, sizeof(TIMEDMETER));
  339. }
  340. }
  341. }
  342. STDMETHODIMP_(void) CCDData::UpdateMeter(LPTIMEDMETER ptm)
  343. {
  344. if (ptm && ptm->hMeter)
  345. {
  346. ptm->dwCount++;
  347. if (ptm->fShowing)
  348. {
  349. if (ptm->hMeter && ((ptm->dwCount % ptm->dwJump) == 0))
  350. {
  351. SendDlgItemMessage( ptm->hMeter, IDC_PROGRESSMETER, PBM_SETPOS, (WPARAM) ptm->dwCount - ptm->dwShowCount, 0);
  352. }
  353. }
  354. else
  355. {
  356. if ((ptm->dwCount % ptm->dwJump) == 0)
  357. {
  358. DWORD dwUsedTime = timeGetTime() - ptm->dwStartTime; // Compute time used
  359. DWORD dwProjected = (ptm->dwRange / ptm->dwCount) * dwUsedTime; // Project Time to complete
  360. DWORD dwProjRemain = dwProjected - dwUsedTime; // Compute projected remaining time
  361. if (dwProjRemain >= 1500) // If it looks like it's going to take a while, put up the meter
  362. {
  363. DWORD dwNumJumps = ptm->dwCount / ptm->dwJump;
  364. DWORD dwJumpTime = dwUsedTime / dwNumJumps;
  365. if (dwJumpTime > 200) // To make sure the meter moves smoothly, re-compute jump count
  366. {
  367. ptm->dwJump = (ptm->dwJump / ((dwJumpTime / 200) + 1)) + 1;
  368. }
  369. ptm->dwShowCount = ptm->dwCount;
  370. SendDlgItemMessage( ptm->hMeter, IDC_PROGRESSMETER, PBM_SETRANGE, 0, MAKELPARAM(0, ptm->dwRange - ptm->dwShowCount));
  371. SendDlgItemMessage( ptm->hMeter, IDC_PROGRESSMETER, PBM_SETPOS, (WPARAM) 0, 0);
  372. ShowWindow(ptm->hMeter,SW_SHOWNORMAL);
  373. UpdateWindow(ptm->hMeter);
  374. ptm->fShowing = TRUE;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. STDMETHODIMP_(void) CCDData::DestroyMeter(LPTIMEDMETER ptm)
  381. {
  382. if (ptm && ptm->hMeter)
  383. {
  384. DestroyWindow(ptm->hMeter);
  385. SetForegroundWindow(ptm->hParent);
  386. memset(ptm, 0, sizeof(LPTIMEDMETER));
  387. }
  388. }
  389. STDMETHODIMP_(void) CCDData::InitDatabase(HSTMT *hstmt)
  390. {
  391. m_pSQL->ExecDirect(hstmt[0], (UCHAR *) TEXT("drop table Titles"), SQL_NTS);
  392. m_pSQL->ExecDirect(hstmt[1], (UCHAR *) TEXT("drop table Tracks"), SQL_NTS);
  393. m_pSQL->ExecDirect(hstmt[2], (UCHAR *) TEXT("drop table Menus"), SQL_NTS);
  394. m_pSQL->ExecDirect(hstmt[3], (UCHAR *) TEXT("drop table Batch"), SQL_NTS);
  395. m_pSQL->ExecDirect(hstmt[0], (UCHAR *) gszTitlesCreate, SQL_NTS);
  396. m_pSQL->ExecDirect(hstmt[1], (UCHAR *) gszTracksCreate, SQL_NTS);
  397. m_pSQL->ExecDirect(hstmt[2], (UCHAR *) gszMenusCreate, SQL_NTS);
  398. m_pSQL->ExecDirect(hstmt[3], (UCHAR *) gszBatchCreate, SQL_NTS);
  399. m_pSQL->FreeStmt(hstmt[0], SQL_CLOSE);
  400. m_pSQL->FreeStmt(hstmt[1], SQL_CLOSE);
  401. m_pSQL->FreeStmt(hstmt[2], SQL_CLOSE);
  402. m_pSQL->FreeStmt(hstmt[3], SQL_CLOSE);
  403. }
  404. STDMETHODIMP_(void) CCDData::SetCursors(HSTMT *hstmt)
  405. {
  406. for (DWORD dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  407. {
  408. m_pSQL->SetStmtOption(hstmt[dwIndex], SQL_CONCURRENCY, SQL_CONCUR_VALUES);
  409. m_pSQL->SetStmtOption(hstmt[dwIndex], SQL_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
  410. m_pSQL->SetStmtOption(hstmt[dwIndex], SQL_ROWSET_SIZE, ROWSET);
  411. }
  412. }
  413. STDMETHODIMP_(void) CCDData::InitCBTable(LPBOUND pbd)
  414. {
  415. memcpy(pbd->cbt.cbTitles, gcbTitles, sizeof(gcbTitles));
  416. memcpy(pbd->cbt.cbTracks, gcbTracks, sizeof(gcbTracks));
  417. memcpy(pbd->cbt.cbMenus, gcbMenus, sizeof(gcbMenus));
  418. memcpy(pbd->cbt.cbBatch, gcbBatch, sizeof(gcbBatch));
  419. }
  420. STDMETHODIMP_(void) CCDData::BindTitles(HSTMT *hstmt, LPBOUND pbd)
  421. {
  422. m_pSQL->BindCol(hstmt[0], 1, SQL_C_ULONG, &(pbd->CDTitle.dwTitleID), sizeof(pbd->CDTitle.dwTitleID), &pbd->cbt.cbTitles[0]);
  423. m_pSQL->BindCol(hstmt[0], 2, SQL_C_WCHAR, pbd->CDTitle.szArtist, sizeof(pbd->CDTitle.szArtist), &pbd->cbt.cbTitles[1]);
  424. m_pSQL->BindCol(hstmt[0], 3, SQL_C_WCHAR, pbd->CDTitle.szTitle, sizeof(pbd->CDTitle.szTitle), &pbd->cbt.cbTitles[2]);
  425. m_pSQL->BindCol(hstmt[0], 4, SQL_C_WCHAR, pbd->CDTitle.szCopyright, sizeof(pbd->CDTitle.szCopyright), &pbd->cbt.cbTitles[3]);
  426. m_pSQL->BindCol(hstmt[0], 5, SQL_C_WCHAR, pbd->CDTitle.szLabel, sizeof(pbd->CDTitle.szLabel), &pbd->cbt.cbTitles[4]);
  427. m_pSQL->BindCol(hstmt[0], 6, SQL_C_WCHAR, pbd->CDTitle.szDate, sizeof(pbd->CDTitle.szDate), &pbd->cbt.cbTitles[5]);
  428. m_pSQL->BindCol(hstmt[0], 7, SQL_C_ULONG, &(pbd->CDTitle.dwNumTracks), sizeof(pbd->CDTitle.dwNumTracks), &pbd->cbt.cbTitles[6]);
  429. m_pSQL->BindCol(hstmt[0], 8, SQL_C_ULONG, &(pbd->CDTitle.dwNumMenus), sizeof(pbd->CDTitle.dwNumMenus), &pbd->cbt.cbTitles[7]);
  430. m_pSQL->BindCol(hstmt[0], 9, SQL_C_WCHAR, pbd->szPlayList, sizeof(pbd->szPlayList), &pbd->cbt.cbTitles[8]);
  431. m_pSQL->BindCol(hstmt[0], 10, SQL_C_WCHAR, pbd->szQuery, sizeof(pbd->szQuery), &pbd->cbt.cbTitles[9]);
  432. }
  433. STDMETHODIMP_(void) CCDData::BindTracks(HSTMT *hstmt, LPBOUND pbd)
  434. {
  435. m_pSQL->BindCol(hstmt[1], 1, SQL_C_ULONG, &(pbd->CDTitle.dwTitleID), sizeof(pbd->CDTitle.dwTitleID), &pbd->cbt.cbTracks[0]);
  436. m_pSQL->BindCol(hstmt[1], 2, SQL_C_ULONG, &(pbd->dwTrackID), sizeof(pbd->dwTrackID), &pbd->cbt.cbTracks[1]);
  437. m_pSQL->BindCol(hstmt[1], 3, SQL_C_WCHAR, pbd->CDTrack.szName, sizeof(pbd->CDTrack.szName), &pbd->cbt.cbTracks[2]);
  438. }
  439. STDMETHODIMP_(void) CCDData::BindMenus(HSTMT *hstmt, LPBOUND pbd)
  440. {
  441. m_pSQL->BindCol(hstmt[2], 1, SQL_C_ULONG, &(pbd->CDTitle.dwTitleID), sizeof(pbd->CDTitle.dwTitleID), &pbd->cbt.cbMenus[0]);
  442. m_pSQL->BindCol(hstmt[2], 2, SQL_C_ULONG, &(pbd->dwMenuID), sizeof(pbd->dwMenuID), &pbd->cbt.cbMenus[1]);
  443. m_pSQL->BindCol(hstmt[2], 3, SQL_C_WCHAR, pbd->CDMenu.szMenuText, sizeof(pbd->CDMenu.szMenuText), &pbd->cbt.cbMenus[2]);
  444. m_pSQL->BindCol(hstmt[2], 4, SQL_C_WCHAR, pbd->szQuery, sizeof(pbd->szQuery), &pbd->cbt.cbMenus[3]);
  445. }
  446. STDMETHODIMP_(void) CCDData::BindBatch(HSTMT *hstmt, LPBOUND pbd)
  447. {
  448. m_pSQL->BindCol(hstmt[3], 1, SQL_C_ULONG, &(pbd->CDTitle.dwTitleID), sizeof(pbd->CDTitle.dwTitleID), &pbd->cbt.cbBatch[0]);
  449. m_pSQL->BindCol(hstmt[3], 2, SQL_C_ULONG, &(pbd->CDTitle.dwNumTracks), sizeof(pbd->CDTitle.dwNumTracks), &pbd->cbt.cbBatch[1]);
  450. m_pSQL->BindCol(hstmt[3], 3, SQL_C_WCHAR, pbd->szQuery, sizeof(pbd->szQuery), &pbd->cbt.cbBatch[2]);
  451. }
  452. STDMETHODIMP_(void) CCDData::SetBindings(HSTMT *hstmt, LPBOUND pbd)
  453. {
  454. BindTitles(hstmt,pbd);
  455. BindTracks(hstmt,pbd);
  456. BindMenus(hstmt,pbd);
  457. BindBatch(hstmt,pbd);
  458. }
  459. STDMETHODIMP_(void) CCDData::ReportError(LPBOUND pbd, HSTMT hstmt)
  460. {
  461. #ifdef DEBUG
  462. UCHAR state[255];
  463. SDWORD dwErr;
  464. UCHAR szErr[SQL_MAX_MESSAGE_LENGTH];
  465. SWORD cbErr;
  466. m_pSQL->Error(pbd->henv, pbd->hdbc, hstmt, state, &dwErr, szErr, SQL_MAX_MESSAGE_LENGTH, &cbErr);
  467. OutputDebugString((TCHAR *) szErr);
  468. if (szErr[0] != TEXT('\0'))
  469. {
  470. OutputDebugString(TEXT("\n"));
  471. }
  472. #endif
  473. }
  474. STDMETHODIMP_(RETCODE) CCDData::AllocStmt(HDBC hdbc, HSTMT *hstmt)
  475. {
  476. RETCODE rc = SQL_SUCCESS;
  477. DWORD dwIndex;
  478. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  479. {
  480. hstmt[dwIndex] = NULL;
  481. }
  482. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  483. {
  484. rc = m_pSQL->AllocStmt(hdbc, &hstmt[dwIndex]);
  485. if (rc != SQL_SUCCESS)
  486. {
  487. break;
  488. }
  489. }
  490. return(rc);
  491. }
  492. STDMETHODIMP_(void) CCDData::FreeStmt(HSTMT *hstmt)
  493. {
  494. RETCODE rc = SQL_SUCCESS;
  495. DWORD dwIndex;
  496. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  497. {
  498. if (hstmt[dwIndex] != NULL)
  499. {
  500. m_pSQL->FreeStmt(hstmt[dwIndex], SQL_DROP);
  501. hstmt[dwIndex] = NULL;
  502. }
  503. }
  504. }
  505. STDMETHODIMP_(void) CCDData::CreateDatabase(void)
  506. {
  507. HENV henv;
  508. HDBC hdbc;
  509. HSTMT hstmt[NUMTABLES];
  510. TCHAR szWinDir[MAX_PATH];
  511. TCHAR szCreateAttr[MAX_PATH];
  512. TCHAR szDSNAttr[MAX_PATH];
  513. if (GetAppDataDir(szWinDir, sizeof(szWinDir)/sizeof(TCHAR)) != 0)
  514. {
  515. wsprintf(szCreateAttr, gszDSNCreate, szWinDir, TEXT('\0'));
  516. wsprintf(szDSNAttr, gszDSNAttr, TEXT('\0'), szWinDir, TEXT('\0'), TEXT('\0'), TEXT('\0'));
  517. if (m_pSQL->ConfigDataSource(NULL, ODBC_ADD_DSN, gszDriverName, szCreateAttr))
  518. {
  519. if (m_pSQL->ConfigDataSource(NULL, ODBC_ADD_DSN, gszDriverName, szDSNAttr))
  520. {
  521. if (m_pSQL->AllocEnv(&henv) == SQL_SUCCESS)
  522. {
  523. if (m_pSQL->AllocConnect(henv, &hdbc) == SQL_SUCCESS)
  524. {
  525. if (m_pSQL->Connect(hdbc, (UCHAR *) gszDSN, SQL_NTS, NULL, 0, NULL, 0) == SQL_SUCCESS)
  526. {
  527. if (AllocStmt(hdbc, hstmt) == SQL_SUCCESS)
  528. {
  529. InitDatabase(hstmt);
  530. }
  531. FreeStmt(hstmt);
  532. }
  533. m_pSQL->Disconnect(hdbc);
  534. }
  535. m_pSQL->FreeConnect(hdbc);
  536. }
  537. m_pSQL->FreeEnv(henv);
  538. }
  539. }
  540. }
  541. }
  542. STDMETHODIMP CCDData::CheckDatabase(HWND hWnd)
  543. {
  544. HRESULT hr = S_OK;
  545. GetSQLPtr(FALSE);
  546. if (!m_pSQL)
  547. {
  548. if (!m_fToldUser)
  549. {
  550. TCHAR szTitle[255];
  551. TCHAR szCaption[255];
  552. LoadString(g_dllInst, IDS_ERROR_NO_ODBC, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  553. LoadString(g_dllInst, IDS_ERROR_SETUP, szCaption, sizeof(szTitle)/sizeof(TCHAR));
  554. MessageBox(hWnd, szTitle, szCaption, MB_OK | MB_ICONEXCLAMATION);
  555. m_fToldUser = TRUE;
  556. }
  557. hr = E_FAIL;
  558. }
  559. return(hr);
  560. }
  561. //finds the dir that is correct for storing cd information
  562. STDMETHODIMP_(DWORD) CCDData::GetAppDataDir(TCHAR* pstrDir, DWORD cchSize)
  563. {
  564. DWORD dwRet = 0;
  565. TCHAR szDataDir[MAX_PATH];
  566. //get the allusers application folder
  567. if (SUCCEEDED(SHGetFolderPath(NULL,CSIDL_APPDATA,NULL,SHGFP_TYPE_CURRENT,pstrDir)))
  568. {
  569. if (PathAppend(pstrDir,TEXT("Microsoft\\CD Player")))
  570. {
  571. SHCreateDirectoryExW(NULL, pstrDir, NULL);
  572. //shorten the pathname, because ODBC can't handle spaces
  573. TCHAR szDir[MAX_PATH];
  574. _tcscpy(szDir,pstrDir);
  575. dwRet = GetShortPathName(szDir,pstrDir,cchSize);
  576. }
  577. }
  578. return (dwRet);
  579. }
  580. STDMETHODIMP CCDData::Initialize(HWND hWnd)
  581. {
  582. TCHAR *pEntries = NULL;
  583. HRESULT hr = S_OK;
  584. DWORD dwCount;
  585. UDWORD row[NUMTABLES];
  586. UWORD rgfRowStat[NUMTABLES][ROWSET];
  587. TCHAR szWinDir[MAX_PATH];
  588. TCHAR szCreateAttr[MAX_PATH];
  589. TIMEDMETER tm;
  590. if (SUCCEEDED(GetSQLPtr(TRUE)))
  591. {
  592. if (GetAppDataDir(szWinDir, sizeof(szWinDir)/sizeof(TCHAR)) != 0)
  593. {
  594. wsprintf(szCreateAttr, gszDSNCreate, szWinDir, TEXT('\0'));
  595. if (m_pSQL->ConfigDataSource(NULL, ODBC_ADD_DSN, gszDriverName, szCreateAttr)) // If this fails, we assume we've already imported the file
  596. {
  597. hr = GetUnknownString(&pEntries, NULL, NULL, SECTION_BUFFER);
  598. if (SUCCEEDED(hr))
  599. {
  600. dwCount = ImportCount(pEntries);
  601. CreateMeter(&tm, hWnd, dwCount, 5, IDS_IMPORTING);
  602. OpenDatabase(TRUE,hWnd);
  603. if (m_henv)
  604. {
  605. TCHAR *szDiscID = pEntries;
  606. DWORD dwIndex;
  607. memset(&m_bd, 0, sizeof(m_bd));
  608. m_bd.henv = m_henv;
  609. m_bd.hdbc = m_hdbc;
  610. InitDatabase(m_hstmt);
  611. InitCBTable(&m_bd);
  612. SetCursors( m_hstmt );
  613. SetBindings( m_hstmt, &m_bd);
  614. m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
  615. m_pSQL->ExecDirect(m_hstmt[0], (UCHAR *) TEXT("select * from Titles"), SQL_NTS);
  616. m_pSQL->ExecDirect(m_hstmt[1], (UCHAR *) TEXT("select * from Tracks"), SQL_NTS);
  617. m_pSQL->ExecDirect(m_hstmt[2], (UCHAR *) TEXT("select * from Menus"), SQL_NTS);
  618. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  619. {
  620. m_pSQL->ExtendedFetch(m_hstmt[dwIndex], SQL_FETCH_FIRST, 1, &row[dwIndex], rgfRowStat[dwIndex]);
  621. }
  622. ImportDatabase(&tm, m_hstmt, szDiscID);
  623. m_pSQL->Transact(SQL_NULL_HENV, m_hdbc, SQL_COMMIT);
  624. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  625. {
  626. m_pSQL->FreeStmt(m_hstmt[dwIndex], SQL_CLOSE);
  627. }
  628. m_pSQL->ExecDirect(m_hstmt[0], (UCHAR *) TEXT("create index TitleIDx on Titles(TitleID)"), SQL_NTS);
  629. m_pSQL->ExecDirect(m_hstmt[1], (UCHAR *) TEXT("create index TitleIDx on Tracks(TitleID)"), SQL_NTS);
  630. m_pSQL->ExecDirect(m_hstmt[2], (UCHAR *) TEXT("create index TitleIDx on Menus(TitleID)"), SQL_NTS);
  631. m_pSQL->Transact(SQL_NULL_HENV, m_hdbc, SQL_COMMIT);
  632. m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
  633. CloseDatabase();
  634. }
  635. DestroyMeter(&tm);
  636. }
  637. if (pEntries)
  638. {
  639. delete pEntries;
  640. }
  641. }
  642. hr = OpenDatabase(FALSE,hWnd); // We either already have a database or we just created one, open it. (If we didn't import OpenDatabase will create new one
  643. }
  644. }
  645. return(hr);
  646. }
  647. STDMETHODIMP CCDData::ConnectToDatabase(WORD fRequest)
  648. {
  649. HRESULT hr = E_FAIL;
  650. TCHAR szWinDir[MAX_PATH];
  651. TCHAR szDSNAttr[MAX_PATH];
  652. if (GetAppDataDir(szWinDir, sizeof(szWinDir)/sizeof(TCHAR)) != 0)
  653. {
  654. wsprintf(szDSNAttr, gszDSNAttr, TEXT('\0'), szWinDir, TEXT('\0'), TEXT('\0'), TEXT('\0'));
  655. if (m_pSQL->ConfigDataSource(NULL, fRequest, gszDriverName, szDSNAttr))
  656. {
  657. if (m_pSQL->AllocEnv(&m_henv) == SQL_SUCCESS)
  658. {
  659. if (m_pSQL->AllocConnect(m_henv, &m_hdbc) == SQL_SUCCESS)
  660. {
  661. if (m_pSQL->Connect(m_hdbc, (UCHAR *) gszDSN, SQL_NTS, NULL, 0, NULL, 0) == SQL_SUCCESS)
  662. {
  663. if (AllocStmt(m_hdbc, m_hstmt) == SQL_SUCCESS)
  664. {
  665. hr = S_OK;
  666. }
  667. }
  668. }
  669. }
  670. }
  671. }
  672. return(hr);
  673. }
  674. STDMETHODIMP CCDData::OpenDatabase(BOOL fCreate, HWND hWnd)
  675. {
  676. HRESULT hr = E_FAIL;
  677. m_henv = NULL;
  678. m_hdbc = NULL;
  679. for (DWORD dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  680. {
  681. m_hstmt[dwIndex] = NULL;
  682. }
  683. hr = ConnectToDatabase(ODBC_ADD_DSN);
  684. if (FAILED(hr)) // Lets try creating the database
  685. {
  686. CreateDatabase();
  687. hr = ConnectToDatabase(ODBC_CONFIG_DSN);
  688. }
  689. else
  690. {
  691. //only do this if connection to database succeeded right off the bat,
  692. //because if we just created a new one, it is in the right format already.
  693. if (IsOldFormat())
  694. {
  695. hr = UpgradeDatabase(hWnd);
  696. }
  697. }
  698. if (FAILED(hr))
  699. {
  700. CloseDatabase();
  701. }
  702. return (hr);
  703. }
  704. STDMETHODIMP_(void) CCDData::CloseDatabase(void)
  705. {
  706. if (m_pSQL)
  707. {
  708. FreeStmt(m_hstmt);
  709. if (m_hdbc)
  710. {
  711. m_pSQL->Disconnect(m_hdbc);
  712. m_pSQL->FreeConnect(m_hdbc);
  713. }
  714. if (m_henv)
  715. {
  716. m_pSQL->FreeEnv(m_henv);
  717. }
  718. }
  719. }
  720. STDMETHODIMP_(DWORD) CCDData::GetNumRows(UCHAR *szDSN)
  721. {
  722. HSTMT hstmt;
  723. DWORD dwCount = 0;
  724. SWORD Type,Cardinality;
  725. SDWORD cbCardinality = 0, cbType = 0;
  726. RETCODE rc;
  727. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  728. {
  729. if (m_pSQL->Statistics(hstmt, NULL, 0, NULL, 0, szDSN, SQL_NTS, SQL_INDEX_ALL, SQL_ENSURE) == SQL_SUCCESS)
  730. {
  731. rc = m_pSQL->BindCol(hstmt, 7, SQL_C_SSHORT, &Type, sizeof(Type), &cbType);
  732. rc = m_pSQL->BindCol(hstmt, 11, SQL_C_SSHORT, &Cardinality, sizeof(Cardinality), &cbCardinality);
  733. if (rc != SQL_SUCCESS)
  734. {
  735. ReportError(&m_bd, hstmt);
  736. }
  737. while (rc == SQL_SUCCESS)
  738. {
  739. rc = m_pSQL->Fetch(hstmt);
  740. if (rc == SQL_SUCCESS)
  741. {
  742. if (Type == SQL_TABLE_STAT)
  743. {
  744. dwCount = (DWORD) Cardinality;
  745. break;
  746. }
  747. }
  748. }
  749. }
  750. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  751. }
  752. return(dwCount);
  753. }
  754. STDMETHODIMP CCDData::ExtractTitle(LPCDTITLE *ppCDTitle)
  755. {
  756. HRESULT hr;
  757. LPCDTITLE pCDTitle = NULL;
  758. m_bd.CDTitle.fLoaded = FALSE;
  759. hr = NewTitle(&pCDTitle, m_bd.CDTitle.dwTitleID, m_bd.CDTitle.dwNumTracks, m_bd.CDTitle.dwNumMenus);
  760. if (SUCCEEDED(hr))
  761. {
  762. DWORD dwTrack = 0;
  763. DWORD dwMenu = 0;
  764. m_bd.CDTitle.pTrackTable = pCDTitle->pTrackTable;
  765. m_bd.CDTitle.pMenuTable = pCDTitle->pMenuTable;
  766. m_bd.CDTitle.pPlayList = pCDTitle->pPlayList;
  767. memcpy(pCDTitle,&m_bd.CDTitle,sizeof(m_bd.CDTitle));
  768. memset(&m_bd.CDTitle, 0, sizeof(m_bd.CDTitle));
  769. DWORD dwSize = lstrlen(m_bd.szQuery) + 1;
  770. if (dwSize)
  771. {
  772. pCDTitle->szTitleQuery = new(TCHAR[dwSize]);
  773. if (pCDTitle->szTitleQuery)
  774. {
  775. lstrcpy(pCDTitle->szTitleQuery, m_bd.szQuery);
  776. }
  777. }
  778. pCDTitle->dwNumPlay = lstrlen(m_bd.szPlayList) >> 1; // Null terminated, two digits per entry (two chars) thus divide by 2
  779. if (pCDTitle->dwNumPlay)
  780. {
  781. pCDTitle->dwNumPlay = min(pCDTitle->dwNumPlay, MAXNUMPLAY);
  782. pCDTitle->pPlayList = new(WORD[pCDTitle->dwNumPlay]);
  783. if (pCDTitle->pPlayList == NULL)
  784. {
  785. pCDTitle->dwNumPlay = 0;
  786. }
  787. else
  788. {
  789. TCHAR *pText = m_bd.szPlayList;
  790. LPWORD pNum = pCDTitle->pPlayList;
  791. DWORD dwIndex = 0;
  792. TCHAR szNum[3];
  793. int iNum;
  794. szNum[2] = TEXT('\0');
  795. for (dwIndex = 0; dwIndex < pCDTitle->dwNumPlay; dwIndex++, pNum++)
  796. {
  797. szNum[0] = *pText++;
  798. szNum[1] = *pText++;
  799. _stscanf(szNum, TEXT("%02x"), &iNum);
  800. *pNum = (WORD) iNum;
  801. }
  802. }
  803. }
  804. }
  805. if (SUCCEEDED(hr) && ppCDTitle)
  806. {
  807. *ppCDTitle = pCDTitle;
  808. }
  809. else if (pCDTitle)
  810. {
  811. DestroyTitle(pCDTitle);
  812. }
  813. return(hr);
  814. }
  815. STDMETHODIMP_(LPCDTITLE) CCDData::FindTitle(LPCDTITLE pCDTitle, DWORD dwTitleID)
  816. {
  817. while (pCDTitle)
  818. {
  819. if (pCDTitle->dwTitleID == dwTitleID)
  820. {
  821. break;
  822. }
  823. pCDTitle = pCDTitle->pNext;
  824. }
  825. return(pCDTitle);
  826. }
  827. STDMETHODIMP CCDData::ExtractTitles(LPCDTITLE *ppCDTitleList, HWND hWnd)
  828. {
  829. HRESULT hr = S_OK;
  830. LPCDTITLE pCDTitle = NULL;;
  831. TIMEDMETER tm;
  832. InitCBTable(&m_bd);
  833. SetCursors(m_hstmt);
  834. SetBindings(m_hstmt, &m_bd);
  835. if (ppCDTitleList == NULL || m_henv == NULL)
  836. {
  837. hr = E_INVALIDARG;
  838. }
  839. else
  840. {
  841. RETCODE rc;
  842. DWORD dwCount = GetNumRows((UCHAR *) gszTitleTable) + GetNumRows((UCHAR *) gszTrackTable) + GetNumRows((UCHAR *) gszMenuTable);
  843. CreateMeter(&tm, hWnd, dwCount, 100, 0);
  844. dwCount = 0;
  845. rc = m_pSQL->ExecDirect(m_hstmt[0], (UCHAR *) TEXT("select * from Titles"), SQL_NTS);
  846. if (rc == SQL_SUCCESS)
  847. {
  848. m_bd.szQuery[0] = TEXT('\0');
  849. while (m_pSQL->Fetch(m_hstmt[0]) == SQL_SUCCESS)
  850. {
  851. hr = ExtractTitle(&pCDTitle);
  852. if (SUCCEEDED(hr))
  853. {
  854. AddTitle(ppCDTitleList, pCDTitle);
  855. UpdateMeter(&tm);
  856. }
  857. m_bd.szQuery[0] = TEXT('\0');
  858. }
  859. if (*ppCDTitleList)
  860. {
  861. hr = S_OK;
  862. }
  863. m_pSQL->FreeStmt(m_hstmt[0], SQL_CLOSE);
  864. m_pSQL->ExecDirect(m_hstmt[1], (UCHAR *) TEXT("select * from Tracks"), SQL_NTS);
  865. pCDTitle = NULL;
  866. while (m_pSQL->Fetch(m_hstmt[1]) == SQL_SUCCESS)
  867. {
  868. if (pCDTitle == NULL || pCDTitle->dwTitleID != m_bd.CDTitle.dwTitleID)
  869. {
  870. pCDTitle = FindTitle(*ppCDTitleList, m_bd.CDTitle.dwTitleID);
  871. }
  872. if (pCDTitle)
  873. {
  874. if (m_bd.dwTrackID < pCDTitle->dwNumTracks)
  875. {
  876. memcpy(&(pCDTitle->pTrackTable[m_bd.dwTrackID]), &(m_bd.CDTrack), sizeof(m_bd.CDTrack));
  877. UpdateMeter(&tm);
  878. }
  879. }
  880. }
  881. m_pSQL->FreeStmt(m_hstmt[1], SQL_CLOSE);
  882. m_pSQL->ExecDirect(m_hstmt[2], (UCHAR *) TEXT("select * from Menus"), SQL_NTS);
  883. pCDTitle = NULL;
  884. m_bd.szQuery[0] = TEXT('\0');
  885. while (m_pSQL->Fetch(m_hstmt[2]) == SQL_SUCCESS)
  886. {
  887. if (pCDTitle == NULL || pCDTitle->dwTitleID != m_bd.CDTitle.dwTitleID)
  888. {
  889. pCDTitle = FindTitle(*ppCDTitleList, m_bd.CDTitle.dwTitleID);
  890. }
  891. if (pCDTitle)
  892. {
  893. if (m_bd.dwMenuID < pCDTitle->dwNumMenus)
  894. {
  895. LPCDMENU pCDMenu = &(pCDTitle->pMenuTable[m_bd.dwMenuID]);
  896. TCHAR *szMenuQuery;
  897. SetMenuQuery(pCDMenu, m_bd.szQuery);
  898. szMenuQuery = pCDMenu->szMenuQuery;
  899. memcpy(pCDMenu, &(m_bd.CDMenu), sizeof(m_bd.CDMenu));
  900. pCDMenu->szMenuQuery = szMenuQuery;
  901. m_bd.szQuery[0] = TEXT('\0');
  902. UpdateMeter(&tm);
  903. }
  904. }
  905. }
  906. m_pSQL->FreeStmt(m_hstmt[2], SQL_CLOSE);
  907. }
  908. DestroyMeter(&tm);
  909. }
  910. return(hr);
  911. }
  912. STDMETHODIMP CCDData::ExtractSingleTitle(LPCDTITLE *ppCDTitle, DWORD dwTitleID)
  913. {
  914. HRESULT hr = S_OK;
  915. LPCDTITLE pCDTitle = NULL;;
  916. InitCBTable(&m_bd);
  917. SetCursors(m_hstmt);
  918. SetBindings( m_hstmt, &m_bd);
  919. if (ppCDTitle == NULL || m_henv == NULL)
  920. {
  921. hr = E_INVALIDARG;
  922. }
  923. else
  924. {
  925. RETCODE rc;
  926. UCHAR szQuery[MAX_PATH];
  927. wsprintf((TCHAR *) szQuery, TEXT("select * from Titles where TitleID = %d"), dwTitleID);
  928. rc = m_pSQL->ExecDirect(m_hstmt[0], szQuery, SQL_NTS);
  929. if (rc != SQL_SUCCESS)
  930. {
  931. hr = E_FAIL;
  932. }
  933. else
  934. {
  935. if (m_pSQL->Fetch(m_hstmt[0]) == SQL_SUCCESS)
  936. {
  937. hr = ExtractTitle(&pCDTitle);
  938. }
  939. else
  940. {
  941. hr = E_FAIL;
  942. }
  943. m_pSQL->FreeStmt(m_hstmt[0], SQL_CLOSE);
  944. if (SUCCEEDED(hr))
  945. {
  946. wsprintf((TCHAR *) szQuery, TEXT("select * from Tracks where TitleID = %d"), dwTitleID);
  947. m_pSQL->ExecDirect(m_hstmt[1], szQuery, SQL_NTS);
  948. while (m_pSQL->Fetch(m_hstmt[1]) == SQL_SUCCESS)
  949. {
  950. if (m_bd.dwTrackID < pCDTitle->dwNumTracks)
  951. {
  952. memcpy(&(pCDTitle->pTrackTable[m_bd.dwTrackID]), &(m_bd.CDTrack), sizeof(m_bd.CDTrack));
  953. }
  954. }
  955. m_pSQL->FreeStmt(m_hstmt[1], SQL_CLOSE);
  956. wsprintf((TCHAR *) szQuery, TEXT("select * from Menus where TitleID = %d"), dwTitleID);
  957. m_pSQL->ExecDirect(m_hstmt[2], szQuery, SQL_NTS);
  958. while (m_pSQL->Fetch(m_hstmt[2]) == SQL_SUCCESS)
  959. {
  960. if (m_bd.dwMenuID < pCDTitle->dwNumMenus)
  961. {
  962. LPCDMENU pCDMenu = &(pCDTitle->pMenuTable[m_bd.dwMenuID]);
  963. TCHAR *szMenuQuery;
  964. SetMenuQuery(pCDMenu, m_bd.szQuery);
  965. szMenuQuery = pCDMenu->szMenuQuery;
  966. memcpy(pCDMenu, &(m_bd.CDMenu), sizeof(m_bd.CDMenu));
  967. pCDMenu->szMenuQuery = szMenuQuery;
  968. m_bd.szQuery[0] = TEXT('\0');
  969. }
  970. }
  971. m_pSQL->FreeStmt(m_hstmt[2], SQL_CLOSE);
  972. }
  973. } //end else main query successful
  974. } //end else args ok
  975. if (SUCCEEDED(hr))
  976. {
  977. *ppCDTitle = pCDTitle;
  978. }
  979. return(hr);
  980. }
  981. STDMETHODIMP_(BOOL) CCDData::QueryDatabase(DWORD dwTitleID, const TCHAR *szTable)
  982. {
  983. BOOL fResult = FALSE;
  984. RETCODE rc;
  985. UCHAR szQuery[MAX_PATH];
  986. HSTMT hstmt;
  987. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  988. {
  989. wsprintf((TCHAR *) szQuery, TEXT("select * from %s where TitleID = %d"), szTable, dwTitleID);
  990. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  991. if (rc == SQL_SUCCESS)
  992. {
  993. if (m_pSQL->Fetch(hstmt) == SQL_SUCCESS)
  994. {
  995. fResult = TRUE;
  996. }
  997. }
  998. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  999. }
  1000. return (fResult);
  1001. }
  1002. STDMETHODIMP_(BOOL) CCDData::QueryTitle(DWORD dwTitleID)
  1003. {
  1004. BOOL fResult = FALSE;
  1005. LPCDTITLE pCDTitle;
  1006. Enter();
  1007. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1008. {
  1009. if (m_pTitleList == NULL) // Database Not in memory, just query database directly
  1010. {
  1011. fResult = QueryDatabase(dwTitleID, gszTitleTable);
  1012. }
  1013. else // Database is in memory, just look here.
  1014. {
  1015. pCDTitle = m_pTitleList;
  1016. while (pCDTitle)
  1017. {
  1018. if (pCDTitle->dwTitleID == dwTitleID)
  1019. {
  1020. if (!pCDTitle->fRemove)
  1021. {
  1022. fResult = TRUE;
  1023. }
  1024. break;
  1025. }
  1026. pCDTitle = pCDTitle->pNext;
  1027. }
  1028. }
  1029. }
  1030. Leave();
  1031. return(fResult);
  1032. }
  1033. STDMETHODIMP CCDData::LockTitle(LPCDTITLE *ppCDTitle, DWORD dwTitleID)
  1034. {
  1035. HRESULT hr = E_INVALIDARG;
  1036. Enter();
  1037. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1038. {
  1039. if (ppCDTitle)
  1040. {
  1041. if (m_pTitleList == NULL) // Database Not in memory, load explicitly
  1042. {
  1043. if (SUCCEEDED(ExtractSingleTitle(ppCDTitle, dwTitleID)))
  1044. {
  1045. (*ppCDTitle)->fLoaded = TRUE;
  1046. (*ppCDTitle)->dwLockCnt = 1;
  1047. hr = S_OK;
  1048. }
  1049. }
  1050. else // Database is in memory, just look here.
  1051. {
  1052. LPCDTITLE pCDTitle;
  1053. pCDTitle = m_pTitleList;
  1054. while (pCDTitle)
  1055. {
  1056. if (pCDTitle->dwTitleID == dwTitleID)
  1057. {
  1058. *ppCDTitle = pCDTitle;
  1059. pCDTitle->fLoaded = FALSE;
  1060. pCDTitle->dwLockCnt++;
  1061. hr = S_OK;
  1062. break;
  1063. }
  1064. pCDTitle = pCDTitle->pNext;
  1065. }
  1066. }
  1067. }
  1068. }
  1069. Leave();
  1070. return(hr);
  1071. }
  1072. STDMETHODIMP_(void) CCDData::UnlockTitle(LPCDTITLE pCDTitle, BOOL fPresist)
  1073. {
  1074. Enter();
  1075. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1076. {
  1077. if (pCDTitle)
  1078. {
  1079. if (fPresist) // They either made a new one, or made changes
  1080. {
  1081. DBSaveTitle(pCDTitle); // write it to database
  1082. }
  1083. if (pCDTitle->fLoaded) // This was NOT pulled from our database (Either locked while we didn't have the database, or was created.
  1084. {
  1085. pCDTitle->dwLockCnt--; // they are unlocking
  1086. if (fPresist && m_dwLoadCnt) // This is a new item, lets add it to load database
  1087. {
  1088. AddTitle(&m_pTitleList, pCDTitle); // Insert into the loaded databased
  1089. }
  1090. else if (pCDTitle->dwLockCnt == 0) // Not being saved and not in database, so nuke it
  1091. {
  1092. DestroyTitle(pCDTitle);
  1093. }
  1094. }
  1095. else // This title was pulled from our database, so just dec the ref
  1096. {
  1097. pCDTitle->dwLockCnt--;
  1098. }
  1099. }
  1100. }
  1101. Leave();
  1102. }
  1103. INT_PTR CALLBACK CCDData::MeterHandler(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1104. {
  1105. BOOL fReturnVal = TRUE;
  1106. switch (msg)
  1107. {
  1108. default:
  1109. fReturnVal = FALSE;
  1110. break;
  1111. case WM_INITDIALOG:
  1112. {
  1113. fReturnVal = TRUE;
  1114. }
  1115. break;
  1116. }
  1117. return fReturnVal;
  1118. }
  1119. STDMETHODIMP CCDData::LoadTitles(HWND hWnd)
  1120. {
  1121. HRESULT hr = E_FAIL;
  1122. Enter();
  1123. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1124. {
  1125. hr = S_OK;
  1126. if (m_pTitleList == NULL)
  1127. {
  1128. hr = ExtractTitles(&m_pTitleList, hWnd);
  1129. }
  1130. if (SUCCEEDED(hr))
  1131. {
  1132. m_dwLoadCnt++;
  1133. }
  1134. }
  1135. Leave();
  1136. return(hr);
  1137. }
  1138. STDMETHODIMP CCDData::PersistTitles()
  1139. {
  1140. Enter();
  1141. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1142. {
  1143. SaveTitles(&m_pTitleList);
  1144. }
  1145. Leave();
  1146. return S_OK;
  1147. }
  1148. STDMETHODIMP CCDData::UnloadTitles()
  1149. {
  1150. HRESULT hr = E_FAIL;
  1151. Enter();
  1152. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1153. {
  1154. if (m_pTitleList)
  1155. {
  1156. m_dwLoadCnt--;
  1157. if (m_dwLoadCnt == 0)
  1158. {
  1159. DestroyTitles(&m_pTitleList);
  1160. }
  1161. hr = S_OK;
  1162. }
  1163. }
  1164. Leave();
  1165. return(hr);
  1166. }
  1167. STDMETHODIMP CCDData::CreateTitle(LPCDTITLE *ppCDTitle, DWORD dwTitleID, DWORD dwNumTracks, DWORD dwNumMenus)
  1168. {
  1169. HRESULT hr = E_FAIL;
  1170. LPCDTITLE pCDTitle;
  1171. Enter();
  1172. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1173. {
  1174. hr = S_OK;
  1175. if (!QueryTitle(dwTitleID)) // Only create a blank if it's not already in database
  1176. {
  1177. RemoveFromBatch(dwTitleID);
  1178. hr = NewTitle(&pCDTitle, dwTitleID, dwNumTracks, dwNumMenus);
  1179. }
  1180. else
  1181. {
  1182. hr = LockTitle(&pCDTitle, dwTitleID); // Let's get return the one we got
  1183. if (SUCCEEDED(hr)) // but first, re-fit it according to params
  1184. {
  1185. if (pCDTitle->dwNumTracks != dwNumTracks)
  1186. {
  1187. if (pCDTitle->pTrackTable)
  1188. {
  1189. delete pCDTitle->pTrackTable;
  1190. }
  1191. pCDTitle->dwNumTracks = dwNumTracks;
  1192. pCDTitle->pTrackTable = new(CDTRACK[dwNumTracks]);
  1193. if (pCDTitle->pTrackTable == NULL)
  1194. {
  1195. hr = E_OUTOFMEMORY;
  1196. }
  1197. }
  1198. if (SUCCEEDED(hr) && pCDTitle->dwNumMenus != dwNumMenus)
  1199. {
  1200. if (pCDTitle->pMenuTable)
  1201. {
  1202. delete pCDTitle->pMenuTable;
  1203. }
  1204. pCDTitle->dwNumMenus = dwNumMenus;
  1205. pCDTitle->pMenuTable = new(CDMENU[dwNumMenus]);
  1206. ZeroMemory(pCDTitle->pMenuTable,sizeof(CDMENU)*dwNumMenus);
  1207. if (pCDTitle->pMenuTable == NULL)
  1208. {
  1209. hr = E_OUTOFMEMORY;
  1210. }
  1211. }
  1212. if (FAILED(hr))
  1213. {
  1214. DestroyTitle(pCDTitle);
  1215. }
  1216. }
  1217. }
  1218. if (SUCCEEDED(hr))
  1219. {
  1220. *ppCDTitle = pCDTitle;
  1221. }
  1222. }
  1223. Leave();
  1224. return(hr);
  1225. }
  1226. STDMETHODIMP CCDData::SetTitleQuery(LPCDTITLE pCDTitle, TCHAR *szTitleQuery)
  1227. {
  1228. HRESULT hr = E_FAIL;
  1229. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1230. {
  1231. if (pCDTitle && szTitleQuery && lstrlen(szTitleQuery) < INTERNET_MAX_PATH_LENGTH)
  1232. {
  1233. if (pCDTitle->szTitleQuery)
  1234. {
  1235. delete pCDTitle->szTitleQuery;
  1236. }
  1237. DWORD dwSize = lstrlen(szTitleQuery) + 1;
  1238. pCDTitle->szTitleQuery = new(TCHAR[dwSize]);
  1239. if (pCDTitle->szTitleQuery == NULL)
  1240. {
  1241. hr = E_OUTOFMEMORY;
  1242. }
  1243. else
  1244. {
  1245. lstrcpy(pCDTitle->szTitleQuery, szTitleQuery);
  1246. hr = S_OK;
  1247. }
  1248. }
  1249. }
  1250. return(hr);
  1251. }
  1252. STDMETHODIMP CCDData::SetMenuQuery(LPCDMENU pCDMenu, TCHAR *szMenuQuery)
  1253. {
  1254. HRESULT hr = E_FAIL;
  1255. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1256. {
  1257. if (pCDMenu && szMenuQuery && lstrlen(szMenuQuery) < INTERNET_MAX_PATH_LENGTH)
  1258. {
  1259. if (pCDMenu->szMenuQuery)
  1260. {
  1261. delete pCDMenu->szMenuQuery;
  1262. }
  1263. DWORD dwSize = lstrlen(szMenuQuery) + 1;
  1264. pCDMenu->szMenuQuery = new(TCHAR[dwSize]);
  1265. if (pCDMenu->szMenuQuery== NULL)
  1266. {
  1267. hr = E_OUTOFMEMORY;
  1268. }
  1269. else
  1270. {
  1271. lstrcpy(pCDMenu->szMenuQuery, szMenuQuery);
  1272. hr = S_OK;
  1273. }
  1274. }
  1275. }
  1276. return(hr);
  1277. }
  1278. STDMETHODIMP CCDData::NewTitle(LPCDTITLE *ppCDTitle, DWORD dwTitleID, DWORD dwNumTracks, DWORD dwNumMenus)
  1279. {
  1280. HRESULT hr = S_OK;
  1281. if (ppCDTitle == NULL || dwTitleID == CDTITLE_NODISC || dwNumTracks == 0)
  1282. {
  1283. hr = E_INVALIDARG;
  1284. }
  1285. else
  1286. {
  1287. LPCDTITLE pCDTitle = new(CDTITLE);
  1288. if (pCDTitle == NULL)
  1289. {
  1290. hr = E_OUTOFMEMORY;
  1291. }
  1292. else
  1293. {
  1294. memset(pCDTitle, 0, sizeof(CDTITLE));
  1295. pCDTitle->dwTitleID = dwTitleID;
  1296. pCDTitle->dwNumTracks = dwNumTracks;
  1297. pCDTitle->dwNumMenus = dwNumMenus;
  1298. pCDTitle->fLoaded = TRUE;
  1299. pCDTitle->dwLockCnt = 1;
  1300. pCDTitle->pTrackTable = new(CDTRACK[dwNumTracks]);
  1301. if (pCDTitle->pTrackTable == NULL)
  1302. {
  1303. hr = E_OUTOFMEMORY;
  1304. }
  1305. else
  1306. {
  1307. memset(pCDTitle->pTrackTable, 0, sizeof(CDTRACK) * dwNumTracks);
  1308. if (dwNumMenus)
  1309. {
  1310. pCDTitle->pMenuTable = new(CDMENU[dwNumMenus]);
  1311. if (pCDTitle->pMenuTable == NULL)
  1312. {
  1313. hr = E_OUTOFMEMORY;
  1314. }
  1315. else
  1316. {
  1317. memset(pCDTitle->pMenuTable, 0, sizeof(CDMENU) * dwNumMenus);
  1318. }
  1319. }
  1320. }
  1321. if (FAILED(hr))
  1322. {
  1323. if (pCDTitle->pMenuTable)
  1324. {
  1325. delete pCDTitle->pMenuTable;
  1326. }
  1327. if (pCDTitle->pTrackTable)
  1328. {
  1329. delete pCDTitle->pTrackTable;
  1330. }
  1331. delete(pCDTitle);
  1332. }
  1333. else
  1334. {
  1335. *ppCDTitle = pCDTitle;
  1336. }
  1337. }
  1338. }
  1339. return(hr);
  1340. }
  1341. STDMETHODIMP_(void) CCDData::DestroyTitle(LPCDTITLE pCDTitle)
  1342. {
  1343. if (pCDTitle)
  1344. {
  1345. if (pCDTitle->szTitleQuery)
  1346. {
  1347. delete pCDTitle->szTitleQuery;
  1348. }
  1349. if (pCDTitle->pTrackTable)
  1350. {
  1351. delete pCDTitle->pTrackTable;
  1352. }
  1353. if (pCDTitle->pPlayList)
  1354. {
  1355. delete pCDTitle->pPlayList;
  1356. }
  1357. if (pCDTitle->pMenuTable)
  1358. {
  1359. for (DWORD dwMenu = 0; dwMenu < pCDTitle->dwNumMenus; dwMenu++)
  1360. {
  1361. TCHAR *szMenuQuery = pCDTitle->pMenuTable[dwMenu].szMenuQuery;
  1362. if (szMenuQuery)
  1363. {
  1364. delete szMenuQuery;
  1365. }
  1366. }
  1367. delete pCDTitle->pMenuTable;
  1368. }
  1369. }
  1370. delete pCDTitle;
  1371. }
  1372. STDMETHODIMP_(void) CCDData::SaveTitle(LPCDTITLE pCDTitle, BOOL fExist)
  1373. {
  1374. UCHAR szQuery[MAX_PATH];
  1375. UDWORD row[NUMTABLES];
  1376. UWORD rgfRowStat[NUMTABLES][ROWSET];
  1377. RETCODE rc;
  1378. if (fExist)
  1379. {
  1380. wsprintf((TCHAR *) szQuery, TEXT("select * from Titles where TitleID = %d"), pCDTitle->dwTitleID);
  1381. rc = m_pSQL->ExecDirect(m_hstmt[0], szQuery, SQL_NTS);
  1382. ReportError(&m_bd, m_hstmt[0]);
  1383. }
  1384. else
  1385. {
  1386. rc = m_pSQL->ExecDirect(m_hstmt[0], (UCHAR *) TEXT("select * from Titles"), SQL_NTS);
  1387. ReportError(&m_bd, m_hstmt[0]);
  1388. }
  1389. rc = m_pSQL->ExtendedFetch(m_hstmt[0], SQL_FETCH_LAST, 1, &row[0], rgfRowStat[0]);
  1390. ReportError(&m_bd, m_hstmt[0]);
  1391. InitCBTable(&m_bd);
  1392. memcpy(&m_bd.CDTitle, pCDTitle, sizeof(CDTITLE));
  1393. if (pCDTitle->szTitleQuery)
  1394. {
  1395. lstrcpy(m_bd.szQuery, pCDTitle->szTitleQuery);
  1396. }
  1397. else
  1398. {
  1399. m_bd.szQuery[0] = TEXT('\0');
  1400. }
  1401. pCDTitle->dwNumPlay = min(pCDTitle->dwNumPlay, MAXNUMPLAY);
  1402. m_bd.szPlayList[0] = TEXT('\0');
  1403. if (pCDTitle->dwNumPlay && pCDTitle->pPlayList)
  1404. {
  1405. DWORD dwIndex;
  1406. TCHAR *pDst = m_bd.szPlayList;
  1407. LPWORD pNum = pCDTitle->pPlayList;
  1408. for (dwIndex = 0; dwIndex < pCDTitle->dwNumPlay; dwIndex++, pNum++)
  1409. {
  1410. wsprintf(pDst, TEXT("%02x"), *pNum);
  1411. while(*pDst != TEXT('\0'))
  1412. {
  1413. pDst++;
  1414. }
  1415. }
  1416. }
  1417. if (fExist)
  1418. {
  1419. rc = m_pSQL->SetPos(m_hstmt[0], 0, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
  1420. // ReportError(&m_bd, m_hstmt[0]);
  1421. }
  1422. else
  1423. {
  1424. rc = m_pSQL->SetPos(m_hstmt[0], 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  1425. // ReportError(&m_bd, m_hstmt[0]);
  1426. }
  1427. }
  1428. STDMETHODIMP_(void) CCDData::SaveTracks(LPCDTITLE pCDTitle, BOOL fExist)
  1429. {
  1430. UCHAR szQuery[MAX_PATH];
  1431. UDWORD row[NUMTABLES];
  1432. UWORD rgfRowStat[NUMTABLES][ROWSET];
  1433. RETCODE rc;
  1434. DWORD dwTrack;
  1435. DWORD dwTitleID = pCDTitle->dwTitleID;
  1436. if (fExist)
  1437. {
  1438. wsprintf((TCHAR *) szQuery, TEXT("select * from Tracks where TitleID = %d"), pCDTitle->dwTitleID);
  1439. rc = m_pSQL->ExecDirect(m_hstmt[1], szQuery, SQL_NTS);
  1440. ReportError(&m_bd, m_hstmt[1]);
  1441. }
  1442. else
  1443. {
  1444. rc = m_pSQL->ExecDirect(m_hstmt[1], (UCHAR *) TEXT("select * from Tracks"), SQL_NTS);
  1445. ReportError(&m_bd, m_hstmt[1]);
  1446. }
  1447. if (fExist)
  1448. {
  1449. rc = m_pSQL->ExtendedFetch(m_hstmt[1], SQL_FETCH_FIRST, 1, &row[0], rgfRowStat[0]);
  1450. ReportError(&m_bd, m_hstmt[1]);
  1451. for (dwTrack = 0; dwTrack < pCDTitle->dwNumTracks; dwTrack++)
  1452. {
  1453. InitCBTable(&m_bd);
  1454. m_bd.CDTitle.dwTitleID = dwTitleID;
  1455. if (m_bd.dwTrackID < pCDTitle->dwNumTracks)
  1456. {
  1457. memcpy(&m_bd.CDTrack, &(pCDTitle->pTrackTable[m_bd.dwTrackID]), sizeof(CDTRACK));
  1458. rc = m_pSQL->SetPos(m_hstmt[1], 0, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
  1459. ReportError(&m_bd, m_hstmt[1]);
  1460. }
  1461. rc = m_pSQL->ExtendedFetch(m_hstmt[1], SQL_FETCH_NEXT, 1, &row[0], rgfRowStat[0]);
  1462. ReportError(&m_bd, m_hstmt[1]);
  1463. }
  1464. }
  1465. else
  1466. {
  1467. rc = m_pSQL->ExtendedFetch(m_hstmt[1], SQL_FETCH_LAST, 1, &row[0], rgfRowStat[0]);
  1468. ReportError(&m_bd, m_hstmt[1]);
  1469. InitCBTable(&m_bd);
  1470. m_bd.CDTitle.dwTitleID = dwTitleID;
  1471. for (dwTrack = 0; dwTrack < pCDTitle->dwNumTracks; dwTrack++)
  1472. {
  1473. m_bd.dwTrackID = dwTrack;
  1474. memcpy(&m_bd.CDTrack, &(pCDTitle->pTrackTable[dwTrack]), sizeof(CDTRACK));
  1475. rc = m_pSQL->SetPos(m_hstmt[1], 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  1476. ReportError(&m_bd, m_hstmt[1]);
  1477. }
  1478. }
  1479. }
  1480. STDMETHODIMP_(void) CCDData::SaveMenus(LPCDTITLE pCDTitle)
  1481. {
  1482. UCHAR szQuery[MAX_PATH];
  1483. UDWORD row[NUMTABLES];
  1484. UWORD rgfRowStat[NUMTABLES][ROWSET];
  1485. RETCODE rc;
  1486. DWORD dwMenu;
  1487. DWORD dwTitleID = pCDTitle->dwTitleID;
  1488. wsprintf((TCHAR *) szQuery, TEXT("delete from Menus where TitleID = %d"), pCDTitle->dwTitleID);
  1489. rc = m_pSQL->ExecDirect(m_hstmt[2], szQuery, SQL_NTS);
  1490. if (pCDTitle->dwNumMenus)
  1491. {
  1492. rc = m_pSQL->ExecDirect(m_hstmt[2], (UCHAR *) TEXT("select * from Menus"), SQL_NTS);
  1493. ReportError(&m_bd, m_hstmt[2]);
  1494. rc = m_pSQL->ExtendedFetch(m_hstmt[2], SQL_FETCH_LAST, 1, &row[0], rgfRowStat[0]);
  1495. ReportError(&m_bd, m_hstmt[2]);
  1496. InitCBTable(&m_bd);
  1497. m_bd.CDTitle.dwTitleID = dwTitleID;
  1498. for (dwMenu = 0; dwMenu < pCDTitle->dwNumMenus; dwMenu++)
  1499. {
  1500. LPCDMENU pCDMenu = &(pCDTitle->pMenuTable[dwMenu]);
  1501. m_bd.dwMenuID = dwMenu;
  1502. memcpy(&m_bd.CDMenu, pCDMenu, sizeof(CDMENU));
  1503. m_bd.szQuery[0] = TEXT('\0');
  1504. if (pCDMenu->szMenuQuery)
  1505. {
  1506. lstrcpy(m_bd.szQuery, pCDMenu->szMenuQuery);
  1507. }
  1508. rc = m_pSQL->SetPos(m_hstmt[2], 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  1509. //ReportError(&m_bd, m_hstmt[2]);
  1510. }
  1511. }
  1512. }
  1513. STDMETHODIMP_(void) CCDData::DBSaveTitle(LPCDTITLE pCDTitle)
  1514. {
  1515. if (pCDTitle)
  1516. {
  1517. RETCODE rc;
  1518. DWORD dwIndex;
  1519. BOOL fExist = QueryDatabase(pCDTitle->dwTitleID, gszTitleTable);
  1520. InitCBTable(&m_bd);
  1521. SetCursors( m_hstmt );
  1522. SetBindings( m_hstmt, &m_bd);
  1523. rc = m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
  1524. ReportError(&m_bd, m_hstmt[0]);
  1525. SaveTitle(pCDTitle, fExist);
  1526. SaveTracks(pCDTitle, fExist);
  1527. SaveMenus(pCDTitle);
  1528. rc = m_pSQL->Transact(SQL_NULL_HENV, m_hdbc, SQL_COMMIT);
  1529. // ReportError(&m_bd, m_hstmt[0]);
  1530. rc = m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
  1531. // ReportError(&m_bd, m_hstmt[0]);
  1532. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  1533. {
  1534. m_pSQL->FreeStmt(m_hstmt[dwIndex], SQL_CLOSE);
  1535. }
  1536. }
  1537. }
  1538. STDMETHODIMP_(void) CCDData::DBRemoveTitle(LPCDTITLE pCDTitle)
  1539. {
  1540. if (pCDTitle && pCDTitle->dwTitleID != CDTITLE_NODISC)
  1541. {
  1542. RETCODE rc;
  1543. UCHAR szQuery[MAX_PATH];
  1544. HSTMT hstmt;
  1545. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  1546. {
  1547. wsprintf((TCHAR *) szQuery, TEXT("delete from Titles where TitleID = %d"), pCDTitle->dwTitleID);
  1548. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  1549. wsprintf((TCHAR *) szQuery, TEXT("delete from Tracks where TitleID = %d"), pCDTitle->dwTitleID);
  1550. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  1551. wsprintf((TCHAR *) szQuery, TEXT("delete from Menus where TitleID = %d"), pCDTitle->dwTitleID);
  1552. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  1553. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  1554. }
  1555. }
  1556. }
  1557. STDMETHODIMP_(void) CCDData::DestroyTitles(LPCDTITLE *ppCDTitles)
  1558. {
  1559. if (ppCDTitles && *ppCDTitles)
  1560. {
  1561. LPCDTITLE pNext;
  1562. LPCDTITLE pCDTitle = *ppCDTitles;
  1563. *ppCDTitles = NULL;
  1564. pNext = pCDTitle;
  1565. while (pCDTitle)
  1566. {
  1567. pNext = pCDTitle->pNext;
  1568. if (pCDTitle->dwLockCnt) // Someone locked a node that was in memory and have unloaded before unlocking
  1569. { // We will abandon the node, it will be destroyed when they unlock it.
  1570. pCDTitle->fLoaded = TRUE;
  1571. pCDTitle->pNext = NULL;
  1572. }
  1573. else
  1574. {
  1575. DestroyTitle(pCDTitle);
  1576. }
  1577. pCDTitle = pNext;
  1578. }
  1579. }
  1580. }
  1581. STDMETHODIMP_(void) CCDData::SaveTitles(LPCDTITLE *ppCDTitles)
  1582. {
  1583. if (ppCDTitles && *ppCDTitles)
  1584. {
  1585. LPCDTITLE pLast = NULL;
  1586. LPCDTITLE pNext;
  1587. LPCDTITLE pCDTitle = *ppCDTitles;
  1588. pNext = pCDTitle;
  1589. while (pCDTitle)
  1590. {
  1591. pNext = pCDTitle->pNext;
  1592. if (pCDTitle->fRemove)
  1593. {
  1594. if (pCDTitle->dwTitleID != DWORD(-1))
  1595. {
  1596. DBRemoveTitle(pCDTitle);
  1597. }
  1598. if (pLast == NULL)
  1599. {
  1600. *ppCDTitles = pNext;
  1601. }
  1602. else
  1603. {
  1604. pLast->pNext = pNext;
  1605. }
  1606. DestroyTitle(pCDTitle);
  1607. }
  1608. else
  1609. {
  1610. if (pCDTitle->fChanged)
  1611. {
  1612. DBSaveTitle(pCDTitle);
  1613. pCDTitle->fChanged = FALSE;
  1614. }
  1615. pLast = pCDTitle;
  1616. }
  1617. pCDTitle = pNext;
  1618. }
  1619. }
  1620. }
  1621. STDMETHODIMP_(void) CCDData::AddTitle(LPCDTITLE *ppCDTitles, LPCDTITLE pCDNewTitle)
  1622. {
  1623. if (ppCDTitles && pCDNewTitle)
  1624. {
  1625. if (*ppCDTitles == NULL) // Inserting into empty list
  1626. {
  1627. *ppCDTitles = pCDNewTitle;
  1628. pCDNewTitle->pNext = NULL;
  1629. }
  1630. else // Insertion sort based on artist name (for view by artist feature)
  1631. {
  1632. LPCDTITLE pCDTitle = *ppCDTitles;
  1633. LPCDTITLE pLast = NULL;
  1634. TCHAR *szArtist = pCDNewTitle->szArtist;
  1635. while (pCDTitle)
  1636. {
  1637. if (lstrcmp(pCDTitle->szArtist, szArtist) >= 0) // we'll only sort by artist, the tree control will sort titles for us
  1638. {
  1639. if (pLast == NULL) // insert at head of list
  1640. {
  1641. pCDNewTitle->pNext = *ppCDTitles;
  1642. *ppCDTitles = pCDNewTitle;
  1643. }
  1644. else
  1645. {
  1646. pCDNewTitle->pNext = pCDTitle;
  1647. pLast->pNext = pCDNewTitle;
  1648. }
  1649. break;
  1650. }
  1651. if (pCDTitle->pNext == NULL) // Insert on end of list
  1652. {
  1653. pCDTitle->pNext = pCDNewTitle;
  1654. pCDNewTitle->pNext = NULL;
  1655. break;
  1656. }
  1657. pLast = pCDTitle;
  1658. pCDTitle = pCDTitle->pNext;
  1659. }
  1660. }
  1661. }
  1662. }
  1663. STDMETHODIMP_(LPCDTITLE) CCDData::GetTitleList(void)
  1664. {
  1665. LPCDTITLE pCDTitle;
  1666. Enter();
  1667. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1668. {
  1669. pCDTitle = m_pTitleList;
  1670. }
  1671. Leave();
  1672. return(pCDTitle);
  1673. }
  1674. STDMETHODIMP_(DWORD) CCDData::GetNumBatched(void)
  1675. {
  1676. DWORD dwCount = 0;
  1677. Enter();
  1678. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1679. {
  1680. if (m_pBatchList == NULL) // Batch Not in memory, just query Batch database directly
  1681. {
  1682. dwCount = GetNumRows((UCHAR *) gszBatchTable);
  1683. }
  1684. else
  1685. {
  1686. LPCDBATCH pCDBatch = m_pBatchList;
  1687. while (pCDBatch)
  1688. {
  1689. if (!pCDBatch->fRemove)
  1690. {
  1691. dwCount++;
  1692. }
  1693. pCDBatch = pCDBatch->pNext;
  1694. }
  1695. }
  1696. }
  1697. Leave();
  1698. return(dwCount);
  1699. }
  1700. STDMETHODIMP_(BOOL) CCDData::FindBatchTitle(LPCDBATCH pCDBatchList, DWORD dwTitleID)
  1701. {
  1702. BOOL fFound = FALSE;
  1703. LPCDBATCH pCDBatch = pCDBatchList;
  1704. while (pCDBatch)
  1705. {
  1706. if (pCDBatch->dwTitleID == dwTitleID)
  1707. {
  1708. if (!pCDBatch->fRemove)
  1709. {
  1710. fFound = TRUE;
  1711. }
  1712. break;
  1713. }
  1714. pCDBatch = pCDBatch->pNext;
  1715. }
  1716. return(fFound);
  1717. }
  1718. STDMETHODIMP_(BOOL) CCDData::QueryBatch(DWORD dwTitleID)
  1719. {
  1720. BOOL fFound = FALSE;
  1721. Enter();
  1722. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1723. {
  1724. if (m_pBatchList == NULL) // Batch Not in memory, just query Batch database directly
  1725. {
  1726. fFound = QueryDatabase(dwTitleID, gszBatchTable);
  1727. }
  1728. else // Batch is in memory, just look here.
  1729. {
  1730. fFound = FindBatchTitle(m_pBatchList, dwTitleID);
  1731. }
  1732. }
  1733. Leave();
  1734. return(fFound);
  1735. }
  1736. STDMETHODIMP CCDData::ExtractBatch(LPCDBATCH *ppCDBatchList, HWND hWnd)
  1737. {
  1738. HRESULT hr = E_FAIL;
  1739. LPCDBATCH pCDBatch= NULL;
  1740. TIMEDMETER tm;
  1741. InitCBTable(&m_bd);
  1742. SetCursors(m_hstmt);
  1743. SetBindings(m_hstmt, &m_bd);
  1744. if (ppCDBatchList == NULL || m_henv == NULL)
  1745. {
  1746. hr = E_INVALIDARG;
  1747. }
  1748. else
  1749. {
  1750. RETCODE rc;
  1751. DWORD dwCount = GetNumRows((UCHAR *) gszBatchTable);
  1752. CreateMeter(&tm, hWnd, dwCount, 100, 0);
  1753. dwCount = 0;
  1754. rc = m_pSQL->ExecDirect(m_hstmt[3], (UCHAR *) TEXT("select * from Batch"), SQL_NTS);
  1755. if (rc == SQL_SUCCESS)
  1756. {
  1757. m_bd.szQuery[0] = TEXT('\0');
  1758. while (m_pSQL->Fetch(m_hstmt[3]) == SQL_SUCCESS)
  1759. {
  1760. pCDBatch = new CDBATCH;
  1761. if (pCDBatch == NULL)
  1762. {
  1763. hr = E_OUTOFMEMORY;
  1764. break;
  1765. }
  1766. else
  1767. {
  1768. DWORD dwSize = lstrlen(m_bd.szQuery) + 1;
  1769. pCDBatch->szTitleQuery = new(TCHAR[dwSize]);
  1770. if (pCDBatch->szTitleQuery == NULL)
  1771. {
  1772. delete pCDBatch;
  1773. hr = E_OUTOFMEMORY;
  1774. break;
  1775. }
  1776. else
  1777. {
  1778. lstrcpy(pCDBatch->szTitleQuery, m_bd.szQuery);
  1779. pCDBatch->dwTitleID = m_bd.CDTitle.dwTitleID;
  1780. pCDBatch->dwNumTracks = m_bd.CDTitle.dwNumTracks;
  1781. pCDBatch->fRemove = FALSE;
  1782. pCDBatch->fFresh = TRUE;
  1783. pCDBatch->pNext = *ppCDBatchList;
  1784. *ppCDBatchList = pCDBatch;
  1785. m_bd.szQuery[0] = TEXT('\0');
  1786. UpdateMeter(&tm);
  1787. hr = S_OK;
  1788. }
  1789. }
  1790. }
  1791. m_pSQL->FreeStmt(m_hstmt[3], SQL_CLOSE);
  1792. }
  1793. DestroyMeter(&tm);
  1794. }
  1795. return(hr);
  1796. }
  1797. STDMETHODIMP CCDData::LoadBatch(HWND hWnd, LPCDBATCH *ppCDBatchList)
  1798. {
  1799. HRESULT hr = E_FAIL;
  1800. Enter();
  1801. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1802. {
  1803. if (ppCDBatchList)
  1804. {
  1805. if (m_pBatchList == NULL)
  1806. {
  1807. hr = ExtractBatch(&m_pBatchList, hWnd);
  1808. if (SUCCEEDED(hr))
  1809. {
  1810. m_dwBatchCnt++;
  1811. *ppCDBatchList = m_pBatchList;
  1812. }
  1813. }
  1814. }
  1815. }
  1816. Leave();
  1817. return(hr);
  1818. }
  1819. STDMETHODIMP_(void) CCDData::DeleteBatch(LPCDBATCH pCDBatch)
  1820. {
  1821. RETCODE rc;
  1822. UCHAR szQuery[MAX_PATH];
  1823. HSTMT hstmt;
  1824. if (pCDBatch->fRemove)
  1825. {
  1826. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  1827. {
  1828. wsprintf((TCHAR *) szQuery, TEXT("delete from Batch where TitleID = %d"), pCDBatch->dwTitleID);
  1829. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  1830. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  1831. }
  1832. }
  1833. if (pCDBatch->szTitleQuery)
  1834. {
  1835. delete pCDBatch->szTitleQuery;
  1836. }
  1837. delete pCDBatch;
  1838. }
  1839. STDMETHODIMP_(void) CCDData::DestroyBatch(LPCDBATCH *ppCDBatchList)
  1840. {
  1841. if (ppCDBatchList && *ppCDBatchList)
  1842. {
  1843. LPCDBATCH pNext;
  1844. LPCDBATCH pCDBatch = *ppCDBatchList;
  1845. *ppCDBatchList = NULL;
  1846. while (pCDBatch)
  1847. {
  1848. pNext = pCDBatch->pNext;
  1849. DeleteBatch(pCDBatch);
  1850. pCDBatch = pNext;
  1851. }
  1852. }
  1853. }
  1854. STDMETHODIMP CCDData::UnloadBatch(LPCDBATCH pCDBatchList)
  1855. {
  1856. HRESULT hr = E_FAIL;
  1857. Enter();
  1858. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1859. {
  1860. if (pCDBatchList == m_pBatchList && m_dwBatchCnt)
  1861. {
  1862. m_dwBatchCnt--;
  1863. if (m_dwBatchCnt == 0)
  1864. {
  1865. DestroyBatch(&m_pBatchList);
  1866. }
  1867. hr = S_OK;
  1868. }
  1869. }
  1870. Leave();
  1871. return(hr);
  1872. }
  1873. STDMETHODIMP CCDData::DumpBatch(void)
  1874. {
  1875. HRESULT hr = E_FAIL;
  1876. Enter();
  1877. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1878. {
  1879. if (m_dwBatchCnt == 0)
  1880. {
  1881. HSTMT hstmt;
  1882. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  1883. {
  1884. m_pSQL->ExecDirect(hstmt, (UCHAR *) TEXT("drop table Batch"), SQL_NTS);
  1885. m_pSQL->ExecDirect(hstmt, (UCHAR *) gszBatchCreate, SQL_NTS);
  1886. m_pSQL->FreeStmt(hstmt, SQL_CLOSE);
  1887. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  1888. hr = S_OK;
  1889. }
  1890. }
  1891. }
  1892. Leave();
  1893. return (hr);
  1894. }
  1895. STDMETHODIMP_(void) CCDData::RemoveFromBatch(DWORD dwTitleID)
  1896. {
  1897. if (QueryBatch(dwTitleID))
  1898. {
  1899. if (m_pBatchList)
  1900. {
  1901. LPCDBATCH pBatch = m_pBatchList;
  1902. while(pBatch)
  1903. {
  1904. if (pBatch->dwTitleID == dwTitleID)
  1905. {
  1906. pBatch->fRemove = TRUE;
  1907. break;
  1908. }
  1909. pBatch = pBatch->pNext;
  1910. }
  1911. }
  1912. else
  1913. {
  1914. RETCODE rc;
  1915. UCHAR szQuery[MAX_PATH];
  1916. HSTMT hstmt;
  1917. if (m_pSQL->AllocStmt(m_hdbc, &hstmt) == SQL_SUCCESS)
  1918. {
  1919. wsprintf((TCHAR *) szQuery, TEXT("delete from Batch where TitleID = %d"), dwTitleID);
  1920. rc = m_pSQL->ExecDirect(hstmt, szQuery, SQL_NTS);
  1921. m_pSQL->FreeStmt(hstmt, SQL_DROP);
  1922. }
  1923. }
  1924. }
  1925. }
  1926. STDMETHODIMP CCDData::AddToBatch(DWORD dwTitleID, TCHAR *szTitleQuery, DWORD dwNumTracks)
  1927. {
  1928. HRESULT hr = E_FAIL;
  1929. Enter();
  1930. if (SUCCEEDED(GetSQLPtr(FALSE)))
  1931. {
  1932. if (!QueryBatch(dwTitleID) && szTitleQuery && (UINT)lstrlen(szTitleQuery) < (sizeof(m_bd.szQuery)/sizeof(TCHAR)))
  1933. {
  1934. RETCODE rc;
  1935. DWORD dwIndex;
  1936. UDWORD row;
  1937. UWORD rgfRowStat[ROWSET];
  1938. InitCBTable(&m_bd);
  1939. SetCursors( m_hstmt );
  1940. SetBindings( m_hstmt, &m_bd);
  1941. m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
  1942. rc = m_pSQL->ExecDirect(m_hstmt[3], (UCHAR *) TEXT("select * from Batch"), SQL_NTS);
  1943. ReportError(&m_bd, m_hstmt[3]);
  1944. rc = m_pSQL->ExtendedFetch(m_hstmt[3], SQL_FETCH_LAST, 1, &row, rgfRowStat);
  1945. ReportError(&m_bd, m_hstmt[3]);
  1946. InitCBTable(&m_bd);
  1947. m_bd.CDTitle.dwTitleID = dwTitleID;
  1948. m_bd.CDTitle.dwNumTracks = dwNumTracks;
  1949. lstrcpy(m_bd.szQuery, szTitleQuery);
  1950. rc = m_pSQL->SetPos(m_hstmt[3], 0, SQL_ADD, SQL_LOCK_NO_CHANGE);
  1951. // ReportError(&m_bd, m_hstmt[3]);
  1952. rc = m_pSQL->Transact(SQL_NULL_HENV, m_hdbc, SQL_COMMIT);
  1953. // ReportError(&m_bd, m_hstmt[3]);
  1954. m_pSQL->SetConnectOption(m_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
  1955. for (dwIndex = 0; dwIndex < NUMTABLES; dwIndex++)
  1956. {
  1957. m_pSQL->FreeStmt(m_hstmt[dwIndex], SQL_CLOSE);
  1958. }
  1959. hr = S_OK;
  1960. }
  1961. }
  1962. Leave();
  1963. return(hr);
  1964. }
  1965. STDMETHODIMP_(BOOL) CCDData::IsOldFormat()
  1966. {
  1967. BOOL fResult = FALSE;
  1968. TCHAR szName[MAX_PATH];
  1969. SQLSMALLINT nName;
  1970. SQLSMALLINT sqlType;
  1971. SQLUINTEGER dwColDef;
  1972. SQLSMALLINT ibScale;
  1973. SQLSMALLINT fNullable;
  1974. RETCODE rc = SQL_SUCCESS;
  1975. rc = m_pSQL->ExecDirect(m_hstmt[0], (UCHAR *) TEXT("select * from Titles"), SQL_NTS);
  1976. if (SQL_SUCCEEDED(rc))
  1977. {
  1978. //check "artist" and "titlequery" columns to find out if this is an old-format db.
  1979. //if either is the old type, then this is an old-format db
  1980. rc = m_pSQL->DescribeCol(m_hstmt[0], 2, (UCHAR*)(&szName), sizeof(szName), &nName, &sqlType, &dwColDef, &ibScale, &fNullable);
  1981. if (SQL_SUCCEEDED(rc))
  1982. {
  1983. if (sqlType != SQL_LONGCHAR_FIELD)
  1984. {
  1985. fResult = TRUE;
  1986. }
  1987. }
  1988. rc = m_pSQL->DescribeCol(m_hstmt[0], 10, (UCHAR*)(&szName), sizeof(szName), &nName, &sqlType, &dwColDef, &ibScale, &fNullable);
  1989. if (SQL_SUCCEEDED(rc))
  1990. {
  1991. if (sqlType == SQL_C_BINARY)
  1992. {
  1993. fResult = TRUE;
  1994. }
  1995. }
  1996. }
  1997. m_pSQL->FreeStmt(m_hstmt[0],SQL_CLOSE);
  1998. return (fResult);
  1999. }
  2000. //helper function to convert ascii hex to unicode chars
  2001. void TranslateToUnicode(TCHAR* pszTrans)
  2002. {
  2003. TCHAR* pszTrans2 = pszTrans;
  2004. int nLen = _tcslen(pszTrans);
  2005. int x = 0;
  2006. while (!((pszTrans2[0] == TEXT('0')) && (pszTrans2[1] == TEXT('0'))))
  2007. {
  2008. TCHAR CH;
  2009. CH = ( pszTrans2 [0] >= TEXT('A') ? ( ( pszTrans2 [0] & 0xDF ) - TEXT('A') ) + 10 :
  2010. ( pszTrans2 [0] - TEXT('0') ) );
  2011. CH *= 16;
  2012. CH += ( pszTrans2 [1] >= TEXT('A') ? ( ( pszTrans2 [1] & 0xDF ) - TEXT('A') ) + 10 :
  2013. ( pszTrans2 [1] - TEXT('0') ) );
  2014. pszTrans[x++] = CH;
  2015. pszTrans2 += 2;
  2016. //get out of the loop if we're at the end of the buffer's length
  2017. if (x >= nLen)
  2018. {
  2019. break;
  2020. }
  2021. }
  2022. pszTrans[x] = 0;
  2023. }
  2024. STDMETHODIMP CCDData::UpgradeDatabase(HWND hWnd)
  2025. {
  2026. HRESULT hr = S_OK;
  2027. HSTMT hstmt = NULL;
  2028. TIMEDMETER tm;
  2029. DWORD dwCount = GetNumRows((UCHAR *) gszTitleTable)
  2030. + GetNumRows((UCHAR *) gszBatchTable);
  2031. //steps:
  2032. //1. Read values from old version of database
  2033. //2. Delete the original database
  2034. //3. Create new database with correct data types
  2035. //4. Put data into new database
  2036. //5. Clean up
  2037. //Step 1: Read values from old version of database
  2038. LPCDBATCH pBatchList = NULL;
  2039. LoadTitles(hWnd); //(also gets tracks and menus)
  2040. LoadBatch(hWnd,&pBatchList);
  2041. //need to copy the batch list to ensure that it isn't already in cached in memory,
  2042. //and therefore rejected by the "AddToBatch" call
  2043. LPCDBATCH pBatchHead = NULL;
  2044. LPCDBATCH pBatchTail = NULL;
  2045. LPCDBATCH pBatch = pBatchList;
  2046. while (pBatch)
  2047. {
  2048. LPCDBATCH pNewBatch = new CDBATCH;
  2049. if (!pNewBatch)
  2050. return E_OUTOFMEMORY;
  2051. memcpy(pNewBatch,pBatch,sizeof(CDBATCH));
  2052. pNewBatch->szTitleQuery = new TCHAR[lstrlen(pBatch->szTitleQuery)+1];
  2053. if (!(pNewBatch->szTitleQuery))
  2054. return E_OUTOFMEMORY;
  2055. _tcscpy(pNewBatch->szTitleQuery,pBatch->szTitleQuery);
  2056. if (!pBatchHead)
  2057. {
  2058. pBatchHead = pNewBatch;
  2059. pBatchTail = pNewBatch;
  2060. }
  2061. else
  2062. {
  2063. pBatchTail->pNext = pNewBatch;
  2064. pBatchTail = pNewBatch;
  2065. }
  2066. pNewBatch->pNext = NULL;
  2067. pBatch = pBatch->pNext;
  2068. }
  2069. UnloadBatch(pBatchList);
  2070. //Step 2: Delete the original database
  2071. CloseDatabase();
  2072. TCHAR szFileName[MAX_PATH];
  2073. GetAppDataDir(szFileName,sizeof(szFileName)/sizeof(TCHAR));
  2074. _tcscat(szFileName,TEXT("\\DeluxeCD.MDB"));
  2075. DeleteFile(szFileName);
  2076. //Step 3: Create new database with correct data types
  2077. CreateDatabase();
  2078. ConnectToDatabase(ODBC_CONFIG_DSN);
  2079. //Step 4: Put data into new database
  2080. CreateMeter(&tm, hWnd, dwCount, 5, IDS_IMPORTING);
  2081. //put all the titles into the new db
  2082. LPCDTITLE pCDTitle = m_pTitleList;
  2083. while (pCDTitle)
  2084. {
  2085. TranslateToUnicode(pCDTitle->szTitleQuery);
  2086. for (DWORD x = 0; x < pCDTitle->dwNumMenus; x++)
  2087. {
  2088. TranslateToUnicode(pCDTitle->pMenuTable[x].szMenuQuery);
  2089. }
  2090. DBSaveTitle(pCDTitle);
  2091. UpdateMeter(&tm);
  2092. pCDTitle = pCDTitle->pNext;
  2093. }
  2094. //put all the batches into the new db
  2095. pBatch = pBatchHead;
  2096. while (pBatch)
  2097. {
  2098. TranslateToUnicode(pBatch->szTitleQuery);
  2099. AddToBatch(pBatch->dwTitleID,pBatch->szTitleQuery,pBatch->dwNumTracks);
  2100. pBatch->fRemove = FALSE;
  2101. UpdateMeter(&tm);
  2102. LPCDBATCH pBatchToDelete = pBatch;
  2103. pBatch = pBatch->pNext;
  2104. delete pBatchToDelete->szTitleQuery;
  2105. delete pBatchToDelete;
  2106. }
  2107. //Step 5: Clean up
  2108. DestroyMeter(&tm);
  2109. return (hr);
  2110. }