--- /dev/null
+// BcasCard.cpp: CBcasCard \83N\83\89\83X\82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93\r
+//\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+#include "W2L.h"\r
+#include "BCasCard.h"\r
+\r
+#ifdef _DEBUG\r
+#undef THIS_FILE\r
+static char THIS_FILE[]=__FILE__;\r
+#define new DEBUG_NEW\r
+#endif\r
+\r
+\r
+//#pragma comment(lib, "WinScard.lib")\r
+\r
+\r
+using std::auto_ptr;\r
+\r
+\r
+CBcasCard::CBcasCard()\r
+ : m_hBcasCard(NULL)\r
+ , m_bIsEstablish(false)\r
+ , m_dwLastError(BCEC_NOERROR)\r
+{\r
+ // \93à\95\94\8fó\91Ô\8f\89\8aú\89»\r
+ memset(&m_BcasCardInfo, 0, sizeof(m_BcasCardInfo));\r
+ memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+\r
+ // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\8am\97§\r
+ if(::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_ScardContext) != SCARD_S_SUCCESS){\r
+ m_dwLastError = BCEC_NOTESTABLISHED;\r
+ }\r
+ else{\r
+ m_bIsEstablish = true;\r
+ \r
+ // \83J\81[\83h\83\8a\81[\83_\97ñ\8b\93\r
+ EnumCardReader();\r
+ }\r
+}\r
+\r
+CBcasCard::~CBcasCard()\r
+{\r
+ CloseCard();\r
+\r
+ // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8aJ\95ú\r
+ if(m_bIsEstablish)::SCardReleaseContext(m_ScardContext);\r
+}\r
+\r
+const DWORD CBcasCard::GetCardReaderNum(void) const\r
+{\r
+ // \83J\81[\83h\83\8a\81[\83_\81[\90\94\82ð\95Ô\82·\r
+ return m_CardReaderArray.size();\r
+}\r
+\r
+LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const\r
+{\r
+ // \83J\81[\83h\83\8a\81[\83_\81[\96¼\82ð\95Ô\82·\r
+ return (dwIndex < GetCardReaderNum())? m_CardReaderArray[dwIndex].c_str() : NULL;\r
+}\r
+\r
+const bool CBcasCard::OpenCard(LPCTSTR lpszReader)\r
+{\r
+ // \83\8a\83\\81[\83X\83}\83l\81[\83W\83\83\83R\83\93\83e\83L\83X\83g\82Ì\8am\97§\r
+ if(!m_bIsEstablish){\r
+ m_dwLastError = BCEC_NOTESTABLISHED;\r
+ return false;\r
+ }\r
+ \r
+ // \88ê\92U\83N\83\8d\81[\83Y\82·\82é\r
+ CloseCard();\r
+\r
+\r
+ if(lpszReader){\r
+ // \8ew\92è\82³\82ê\82½\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+ DWORD dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED;\r
+ \r
+ if(::SCardConnect(m_ScardContext, lpszReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &m_hBcasCard, &dwActiveProtocol) != SCARD_S_SUCCESS){\r
+ m_dwLastError = BCEC_CARDOPENERROR;\r
+ return false;\r
+ }\r
+\r
+ if(dwActiveProtocol != SCARD_PROTOCOL_T1){\r
+ CloseCard();\r
+ m_dwLastError = BCEC_CARDOPENERROR;\r
+ return false;\r
+ }\r
+ }\r
+ else{\r
+ // \91S\82Ä\82Ì\83J\81[\83h\83\8a\81[\83_\82É\91Î\82µ\82Ä\83I\81[\83v\83\93\82ð\8e\8e\82Ý\82é\r
+ DWORD dwIndex = 0UL;\r
+ \r
+ while(GetCardReaderName(dwIndex)){\r
+ if(OpenCard(GetCardReaderName(dwIndex++)))return true; \r
+ }\r
+ \r
+ return false;\r
+ }\r
+\r
+ // \83J\81[\83h\8f\89\8aú\89»\r
+ if(!InitialSetting())return false;\r
+\r
+ m_dwLastError = BCEC_NOERROR;\r
+\r
+ return true;\r
+}\r
+\r
+void CBcasCard::CloseCard(void)\r
+{\r
+ // \83J\81[\83h\82ð\83N\83\8d\81[\83Y\82·\82é\r
+ if(m_hBcasCard){\r
+ ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD);\r
+ m_hBcasCard = NULL;\r
+ }\r
+}\r
+\r
+const DWORD CBcasCard::GetLastError(void) const\r
+{\r
+ // \8dÅ\8cã\82É\94\90¶\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
+ return m_dwLastError;\r
+}\r
+\r
+const bool CBcasCard::EnumCardReader(void)\r
+{\r
+ // \83J\81[\83h\83\8a\81[\83_\82ð\97ñ\8b\93\82·\82é\r
+ DWORD dwBuffSize = 0UL;\r
+ \r
+ switch(::SCardListReaders(m_ScardContext, NULL, NULL, &dwBuffSize)){\r
+ case SCARD_E_NO_READERS_AVAILABLE :\r
+ // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+ m_dwLastError = BCEC_NOCARDREADERS;\r
+ return false;\r
+\r
+ case SCARD_S_SUCCESS :\r
+ // \83o\83b\83t\83@\83T\83C\83Y\8eæ\93¾\90¬\8c÷\r
+ break;\r
+ \r
+ default:\r
+ // \83G\83\89\81[\r
+ m_dwLastError = BCEC_INTERNALERROR; \r
+ return false;\r
+ }\r
+\r
+ // \83o\83b\83t\83@\8am\95Û\r
+ auto_ptr<TCHAR> szReaders(new TCHAR[dwBuffSize]);\r
+\r
+ switch(::SCardListReaders(m_ScardContext, NULL, szReaders.get(), &dwBuffSize)){\r
+ case SCARD_E_NO_READERS_AVAILABLE :\r
+ // \83J\81[\83h\83\8a\81[\83_\82ª\8c©\82Â\82©\82ç\82È\82¢\r
+ m_dwLastError = BCEC_NOCARDREADERS;\r
+ return false;\r
+\r
+ case SCARD_S_SUCCESS : {\r
+ // \83J\81[\83h\83\8a\81[\83_\96¼\95Û\91¶\r
+ LPTSTR lpszCurReader = szReaders.get();\r
+ m_CardReaderArray.clear();\r
+ \r
+ while(*lpszCurReader){\r
+ m_CardReaderArray.push_back(lpszCurReader);\r
+ lpszCurReader += m_CardReaderArray.back().length() + 1UL;\r
+ }\r
+ \r
+ break;\r
+ }\r
+ \r
+ default:\r
+ // \83G\83\89\81[\r
+ m_dwLastError = BCEC_INTERNALERROR; \r
+ return false;\r
+ }\r
+\r
+ m_dwLastError = BCEC_NOERROR;\r
+\r
+ return true;\r
+}\r
+\r
+const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize)\r
+{\r
+ DWORD dwRecvSize = dwMaxRecv;\r
+\r
+ // \83f\81[\83^\91\97\8eó\90M\r
+ DWORD dwReturn = ::SCardTransmit(m_hBcasCard, SCARD_PCI_T1, pSendData, dwSendSize, NULL, pRecvData, &dwRecvSize);\r
+ \r
+ // \8eó\90M\83T\83C\83Y\8ai\94[\r
+ if(pdwRecvSize)*pdwRecvSize = dwRecvSize;\r
+\r
+ return (dwReturn == SCARD_S_SUCCESS)? true : false;\r
+}\r
+\r
+const bool CBcasCard::InitialSetting(void)\r
+{\r
+ static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U};\r
+\r
+ // \81uInitial Setting Conditions Command\81v\82ð\8f\88\97\9d\82·\82é\r
+ if(!m_hBcasCard){\r
+ m_dwLastError = BCEC_CARDNOTOPEN;\r
+ return false;\r
+ }\r
+\r
+ // \83o\83b\83t\83@\8f\80\94õ\r
+ DWORD dwRecvSize = 0UL;\r
+ BYTE RecvData[1024];\r
+ memset(RecvData, 0, sizeof(RecvData));\r
+ \r
+ // \83R\83}\83\93\83h\91\97\90M\r
+ if(!TransmitCommand(InitSettingCmd, sizeof(InitSettingCmd), RecvData, sizeof(RecvData), &dwRecvSize)){\r
+ m_dwLastError = BCEC_TRANSMITERROR;\r
+ return false;\r
+ }\r
+\r
+ if(dwRecvSize < 57UL){\r
+ m_dwLastError = BCEC_TRANSMITERROR;\r
+ return false; \r
+ }\r
+\r
+ // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+ memcpy(m_BcasCardInfo.BcasCardID, &RecvData[8], 6UL); // +8 Card ID\r
+ memcpy(m_BcasCardInfo.SystemKey, &RecvData[16], 32UL); // +16 Descrambling system key\r
+ memcpy(m_BcasCardInfo.InitialCbc, &RecvData[48], 8UL); // +48 Descrambler CBC initial value\r
+\r
+ // ECM\83X\83e\81[\83^\83X\8f\89\8aú\89»\r
+ memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+\r
+ return true;\r
+}\r
+\r
+const BYTE * CBcasCard::GetBcasCardID(void)\r
+{\r
+ // Card ID \82ð\95Ô\82·\r
+ if(!m_hBcasCard){\r
+ m_dwLastError = BCEC_CARDNOTOPEN;\r
+ return NULL;\r
+ }\r
+ \r
+ m_dwLastError = BCEC_NOERROR;\r
+ \r
+ return m_BcasCardInfo.BcasCardID;\r
+}\r
+\r
+const BYTE * CBcasCard::GetInitialCbc(void)\r
+{\r
+ // Descrambler CBC Initial Value \82ð\95Ô\82·\r
+ if(!m_hBcasCard){\r
+ m_dwLastError = BCEC_CARDNOTOPEN;\r
+ return NULL;\r
+ }\r
+ \r
+ m_dwLastError = BCEC_NOERROR;\r
+ \r
+ return m_BcasCardInfo.InitialCbc;\r
+}\r
+\r
+const BYTE * CBcasCard::GetSystemKey(void)\r
+{\r
+ // Descrambling System Key \82ð\95Ô\82·\r
+ if(!m_hBcasCard){\r
+ m_dwLastError = BCEC_CARDNOTOPEN;\r
+ return NULL;\r
+ }\r
+ \r
+ m_dwLastError = BCEC_NOERROR;\r
+ \r
+ return m_BcasCardInfo.SystemKey;\r
+}\r
+\r
+const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+ static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U};\r
+\r
+ // \81uECM Receive Command\81v\82ð\8f\88\97\9d\82·\82é\r
+ if(!m_hBcasCard){\r
+ m_dwLastError = BCEC_CARDNOTOPEN;\r
+ return NULL;\r
+ }\r
+\r
+ // ECM\83T\83C\83Y\82ð\83`\83F\83b\83N\r
+ if(!pEcmData || (dwEcmSize < 30UL) || (dwEcmSize > 256UL)){\r
+ m_dwLastError = BCEC_BADARGUMENT;\r
+ return NULL;\r
+ }\r
+\r
+ // \83L\83\83\83b\83V\83\85\82ð\83`\83F\83b\83N\82·\82é\r
+ if(!StoreEcmData(pEcmData, dwEcmSize)){\r
+ // ECM\82ª\93¯\88ê\82Ì\8fê\8d\87\82Í\83L\83\83\83b\83V\83\85\8dÏ\82ÝKs\82ð\95Ô\82·\r
+ m_dwLastError = BCEC_NOERROR;\r
+ return m_EcmStatus.KsData;\r
+ }\r
+\r
+ // \83o\83b\83t\83@\8f\80\94õ\r
+ DWORD dwRecvSize = 0UL;\r
+ BYTE SendData[1024];\r
+ BYTE RecvData[1024];\r
+ memset(RecvData, 0, sizeof(RecvData));\r
+\r
+ // \83R\83}\83\93\83h\8d\\92z\r
+ memcpy(SendData, EcmReceiveCmd, sizeof(EcmReceiveCmd)); // CLA, INS, P1, P2\r
+ SendData[sizeof(EcmReceiveCmd)] = (BYTE)dwEcmSize; // COMMAND DATA LENGTH\r
+ memcpy(&SendData[sizeof(EcmReceiveCmd) + 1], pEcmData, dwEcmSize); // ECM\r
+ SendData[sizeof(EcmReceiveCmd) + dwEcmSize + 1] = 0x00U; // RESPONSE DATA LENGTH\r
+\r
+ // \83R\83}\83\93\83h\91\97\90M\r
+ if(!TransmitCommand(SendData, sizeof(EcmReceiveCmd) + dwEcmSize + 2UL, RecvData, sizeof(RecvData), &dwRecvSize)){\r
+ memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+ m_dwLastError = BCEC_TRANSMITERROR;\r
+ return NULL;\r
+ }\r
+\r
+ // \83T\83C\83Y\83`\83F\83b\83N\r
+ if(dwRecvSize != 25UL){\r
+ memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
+ m_dwLastError = BCEC_TRANSMITERROR;\r
+ return NULL;\r
+ } \r
+ \r
+ // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
+ memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData));\r
+\r
+ // \83\8a\83^\81[\83\93\83R\81[\83h\89ð\90Í\r
+ switch(((WORD)RecvData[4] << 8) | (WORD)RecvData[5]){\r
+ // Purchased: Viewing\r
+ case 0x0200U : // Payment-deferred PPV\r
+ case 0x0400U : // Prepaid PPV\r
+ case 0x0800U : // Tier\r
+ m_dwLastError = BCEC_NOERROR;\r
+ return m_EcmStatus.KsData;\r
+ \r
+ // \8fã\8bL\88È\8aO(\8e\8b\92®\95s\89Â)\r
+ default :\r
+ m_dwLastError = BCEC_ECMREFUSED;\r
+ return NULL;\r
+ }\r
+}\r
+\r
+const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize)\r
+{\r
+ bool bUpdate = false;\r
+ \r
+ // ECM\83f\81[\83^\94ä\8ar\r
+ if(m_EcmStatus.dwLastEcmSize != dwEcmSize){\r
+ // \83T\83C\83Y\82ª\95Ï\89»\82µ\82½\r
+ bUpdate = true;\r
+ }\r
+ else{\r
+ // \83T\83C\83Y\82ª\93¯\82¶\8fê\8d\87\82Í\83f\81[\83^\82ð\83`\83F\83b\83N\82·\82é\r
+ for(DWORD dwPos = 0UL ; dwPos < dwEcmSize ; dwPos++){\r
+ if(pEcmData[dwPos] != m_EcmStatus.LastEcmData[dwPos]){\r
+ // \83f\81[\83^\82ª\95s\88ê\92v\r
+ bUpdate = true;\r
+ break;\r
+ } \r
+ }\r
+ }\r
+\r
+ // ECM\83f\81[\83^\82ð\95Û\91¶\82·\82é\r
+ if(bUpdate){\r
+ m_EcmStatus.dwLastEcmSize = dwEcmSize;\r
+ memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize);\r
+ }\r
+\r
+ return bUpdate;\r
+}\r