// DICOMSRV.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "DICOMSRV.h" #include "SRVDlg.h" #include "ConfDlg.h" #include #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES -1 #endif ///////////////////////////////////////////////////////////////////////////// // CDICOMSRVApp BEGIN_MESSAGE_MAP(CDICOMSRVApp, CWinApp) //{{AFX_MSG_MAP(CDICOMSRVApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDICOMSRVApp construction CDICOMSRVApp::CDICOMSRVApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance m_hWndParent = 0; m_bValidPrivateKeyPassword = FALSE; } ///////////////////////////////////////////////////////////////////////////// // The one and only CDICOMSRVApp object CDICOMSRVApp theApp; ///////////////////////////////////////////////////////////////////////////// // CDICOMSRVApp initialization BOOL CDICOMSRVApp::InitInstance() { AfxEnableControlContainer(); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif LBase::LoadLibraries(LT_KRN | LT_DIS | LT_FIL | LT_IMG | LT_DLG); LDialogBase::Initialize(DLG_INIT_COLOR); WRPUNLOCKSUPPORT(); TCHAR szBuffer[MAX_PATH]; if (GetModuleFileName(NULL, szBuffer, MAX_PATH)) { m_sApplicationFolder = szBuffer; m_sApplicationFolder = m_sApplicationFolder.Left(m_sApplicationFolder.ReverseFind('\\') + 1); } if (!LoadServerSettings()) // Failed to load the server settings? { CConfigDlg ConfigDlg; // Set initial values ConfigDlg.m_sMdbFileFolder = m_sApplicationFolder + DEFAULT_IMAGES_FOLDERNAME; ConfigDlg.m_sImagesFolder = m_sApplicationFolder + DEFAULT_IMAGES_FOLDERNAME; ConfigDlg.m_sTempFilesFolder = m_sApplicationFolder + DEFAULT_TEMP_FOLDERNAME; // Display the dialog box if (ConfigDlg.DoModal() != IDOK) { return FALSE; } // The DICOM images folder m_sImagesFolder = ConfigDlg.m_sImagesFolder; m_bSaveServerSettings = PrepareFolder(m_sImagesFolder, DEFAULT_IMAGES_FOLDERNAME); // The temporary files folder m_sTempFilesFolder = ConfigDlg.m_sTempFilesFolder; m_bSaveServerSettings = PrepareFolder(m_sTempFilesFolder, DEFAULT_TEMP_FOLDERNAME) && m_bSaveServerSettings; if (!PrepareDatabase(ConfigDlg.m_sMdbFileFolder)) { return FALSE; } // Set default values for the other server settings m_sServerAETitle = "LEAD_SERVER"; m_uServerPort = 104; m_nTimeOut = 1; m_nMaxClients = 5; m_bGenerateEventsLogFile = TRUE; m_bSaveReceivedCSs = TRUE; m_bSaveReceivedDSs = FALSE; m_bSaveSentDSs = FALSE; m_sLogFolder = m_sApplicationFolder + DEFAULT_LOGS_FOLDERNAME; PrepareFolder(m_sLogFolder); } else { m_bSaveServerSettings = TRUE; PrepareFolder(m_sImagesFolder, DEFAULT_IMAGES_FOLDERNAME); PrepareFolder(m_sTempFilesFolder, DEFAULT_TEMP_FOLDERNAME); PrepareFolder(m_sLogFolder, DEFAULT_LOGS_FOLDERNAME); } CDICOMSRVDlg ServerDlg; m_pMainWnd = &ServerDlg; int nResponse = ServerDlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } BOOL CDICOMSRVApp::SaveServerSettings() const { if (!m_bSaveServerSettings) { return TRUE; } CFile File; if (!File.Open(m_sApplicationFolder + SERVER_SETTINGS_FILENAME, CFile::modeCreate | CFile::typeBinary | CFile::modeWrite | CFile::shareExclusive)) { return FALSE; } if (!SaveSetting(File, m_sConnectionString)) return FALSE; if (!SaveSetting(File, m_sImagesFolder)) return FALSE; if (!SaveSetting(File, m_sTempFilesFolder)) return FALSE; if (!SaveSetting(File, m_sServerAETitle)) return FALSE; CString sSetting; char szBuffer[64]; itoa(m_uServerPort, szBuffer, 10); sSetting = szBuffer; if (!SaveSetting(File, sSetting)) return FALSE; itoa(m_nTimeOut, szBuffer, 10); sSetting = szBuffer; if (!SaveSetting(File, sSetting)) return FALSE; itoa(m_nMaxClients, szBuffer, 10); sSetting = szBuffer; if (!SaveSetting(File, sSetting)) return FALSE; sSetting = m_bGenerateEventsLogFile ? "1" : "0"; if (!SaveSetting(File, sSetting)) return FALSE; sSetting = m_bSaveReceivedCSs ? "1" : "0"; if (!SaveSetting(File, sSetting)) return FALSE; sSetting = m_bSaveReceivedDSs ? "1" : "0"; if (!SaveSetting(File, sSetting)) return FALSE; sSetting = m_bSaveSentDSs ? "1" : "0"; if (!SaveSetting(File, sSetting)) return FALSE; if (!SaveSetting(File, m_sLogFolder)) return FALSE; return TRUE; } BOOL CDICOMSRVApp::LoadServerSettings() { CFile File; if (!File.Open(m_sApplicationFolder + SERVER_SETTINGS_FILENAME, CFile::modeRead | CFile::typeBinary | CFile::shareDenyWrite)) { return FALSE; } if (!LoadSetting(File, m_sConnectionString)) return FALSE; if (!LoadSetting(File, m_sImagesFolder)) return FALSE; if (!LoadSetting(File, m_sTempFilesFolder)) return FALSE; if (!LoadSetting(File, m_sServerAETitle)) return FALSE; CString sSetting; if (!LoadSetting(File, sSetting)) return FALSE; m_uServerPort = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_nTimeOut = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_nMaxClients = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_bGenerateEventsLogFile = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_bSaveReceivedCSs = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_bSaveReceivedDSs = atoi(sSetting); if (!LoadSetting(File, sSetting)) return FALSE; m_bSaveSentDSs = atoi(sSetting); if (!LoadSetting(File, m_sLogFolder)) return FALSE; return TRUE; } BOOL CDICOMSRVApp::SaveSetting(CFile& File, const CString& sSetting) const { UINT uSize = sSetting.GetLength() + 1; try { File.Write(&uSize, sizeof(uSize)); File.Write(sSetting, uSize); } catch(...) { return FALSE; } return TRUE; } BOOL CDICOMSRVApp::LoadSetting(CFile& File, CString& sSetting) { UINT uSize; UINT uBytesRead; LPSTR pszSetting = NULL; try { uBytesRead = File.Read(&uSize, sizeof(uSize)); if (uBytesRead != sizeof(uSize)) { return FALSE; } pszSetting = new CHAR[uSize]; if (!pszSetting) { return FALSE; } uBytesRead = File.Read(pszSetting, uSize); if (uBytesRead != uSize) { delete [] pszSetting; return FALSE; } sSetting = pszSetting; delete [] pszSetting; } catch(...) { if (pszSetting) { delete [] pszSetting; } return FALSE; } return TRUE; } BOOL CDICOMSRVApp::PrepareDatabase(CString& sMdbFolder) { if (!PrepareFolder(sMdbFolder)) { AfxMessageBox("Failed to create the folder which the database file should be copied to.", MB_OK | MB_ICONSTOP); return FALSE; } CString sNewMdbFile = sMdbFolder + MDB_FILENAME; // At first, we will assume that the application is running from the "Bin" subfolder of // the folder where LEADTOOLS is installed. CString sLeadToolsFolder; if (m_sApplicationFolder.GetLength()) { sLeadToolsFolder = m_sApplicationFolder.Left(m_sApplicationFolder.GetLength() - 1); sLeadToolsFolder = sLeadToolsFolder.Left(sLeadToolsFolder.ReverseFind('\\') + 1); } CString sMessage; WIN32_FIND_DATA FileData; HANDLE hFind; // Locate the database file CString sExistingMdbFile = sLeadToolsFolder + "Images\\" + MDB_FILENAME; hFind = FindFirstFile(sExistingMdbFile, &FileData); if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); } else { // Prompt the user to locate the file sMessage = "Failed to locate the database file (MDB) used by this demo. Do you want " \ "to locate it yourself?\n\n" \ "Note: A sample MDB file is located under the \"Images\" directory created " \ "by LEADTOOLS.\n" \ "If the installation path for LEADTOOLS is for example:\n" \ "\"C:\\LEAD Technologies, Inc\\LEADTOOLS\"\n" \ "then the path for the MDB file will be:\n" \ "\"C:\\LEAD Technologies, Inc\\LEADTOOLS\\Images\\" MDB_FILENAME "\"."; if (AfxMessageBox(sMessage, MB_YESNO) != IDYES) { return FALSE; } sExistingMdbFile = MDB_FILENAME; if (!GetFile("Microsoft Access Databases (*.mdb)\0*.mdb\0All Files (*.*)\0*.*\0", "Locate MDB File", sExistingMdbFile)) { return FALSE; } } // Copy the existing databse file if (!CopyFile(sExistingMdbFile, sNewMdbFile, FALSE)) { AfxMessageBox("Failed to copy the database file.", MB_OK | MB_ICONSTOP); return FALSE; } // The connection string m_sConnectionString = "DRIVER={Microsoft Access Driver (*.mdb)};" \ "DBQ=" + sNewMdbFile; // Now we need to copy the sample DICOM images to the DICOM images folder. Again, we will // assume that the application is running from the "Bin" subfolder of the folder where // LEADTOOLS is installed. int i; CString ExistingDicomFiles[] = SAMPLE_DICOM_IMAGES; hFind = FindFirstFile(sLeadToolsFolder + "Images\\" + ExistingDicomFiles[0], &FileData); if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); for (i = 0; i < sizeof(ExistingDicomFiles) / sizeof(ExistingDicomFiles[0]); i++) { ExistingDicomFiles[i] = sLeadToolsFolder + "Images\\" + ExistingDicomFiles[i]; } } else { // Prompt the user to specify the location of the sample DICOM images sMessage = "Failed to locate the sample DICOM images shipped with this demo. Do you " \ "want to locate them yourself?\nIf you press No, the demo will start " \ "with an empty database.\n\n" \ "Note: The sample DICOM images, which ship with LEADTOOLS, are located " \ "under the \"Images\" directory created by LEADTOOLS.\n" \ "If the installation path for LEADTOOLS is for example:\n" \ "\"C:\\LEAD Technologies, Inc\\LEADTOOLS\"\n" \ "then the path for the sample images will be:\n" \ "\"C:\\LEAD Technologies, Inc\\LEADTOOLS\\Images\"."; if (AfxMessageBox(sMessage, MB_YESNO) != IDYES) { EmptyDatabase(); return TRUE; } else { CString sSelectedFolder; if (GetFolder(NULL, sSelectedFolder, TEXT("Specify the folder of the sample DICOM images:"))) { sSelectedFolder += '\\'; for (i = 0; i < sizeof(ExistingDicomFiles) / sizeof(ExistingDicomFiles[0]); i++) { ExistingDicomFiles[i] = sSelectedFolder + ExistingDicomFiles[i]; } } else { EmptyDatabase(); return TRUE; } } } CString NewDicomFiles[sizeof(ExistingDicomFiles) / sizeof(ExistingDicomFiles[0])]; for (i = 0; i < sizeof(ExistingDicomFiles) / sizeof(ExistingDicomFiles[0]); i++) { if (!GetNewFilename(ExistingDicomFiles[i], NewDicomFiles[i]) || !CopyFile(ExistingDicomFiles[i], NewDicomFiles[i], FALSE)) { for (int j = 0; j < i; j++) { DeleteFile(NewDicomFiles[j]); } AfxMessageBox("Failed to copy the sample DICOM images. The demo will start with " \ "an empty database."); EmptyDatabase(); return TRUE; } } return TRUE; } BOOL CDICOMSRVApp::GetFile(LPCTSTR pszFilter, LPCTSTR pszTitle, CString& sFile) const { OPENFILENAME ofn; TCHAR szFile[MAX_PATH]; lstrcpyn(szFile, sFile, MAX_PATH); // Initialize the OPENFILENAME structure ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.lpstrFilter = pszFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile) / sizeof(TCHAR); ofn.lpstrTitle = pszTitle; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; // Display the Open dialog box if (GetOpenFileName(&ofn)) { sFile = szFile; return TRUE; } return FALSE; } BOOL CDICOMSRVApp::GetNewFilename(const CString& sExistingDicomFile, CString& sNewFilename) const { LDicomDS DataSet((L_CHAR*)(LPCTSTR) m_sTempFilesFolder); if (DataSet.LoadDS((L_CHAR*)(LPCTSTR) sExistingDicomFile, DS_LOAD_CLOSE) == DICOM_SUCCESS) { pDICOMELEMENT pElement = DataSet.FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); if (pElement) { sNewFilename = DataSet.GetStringValue(pElement, 0, 1); if (sNewFilename.GetLength()) { sNewFilename = m_sImagesFolder + sNewFilename + ".dcm"; return TRUE; } } } return FALSE; } BOOL CDICOMSRVApp::GetFolder(HWND hWndOwner, CString& sSelectedFolder, LPCTSTR pszTitle) { BROWSEINFOA bi; bi.hwndOwner = hWndOwner; bi.pidlRoot = NULL; bi.pszDisplayName = NULL; bi.lpszTitle = pszTitle; bi.ulFlags = BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; bi.lParam = 0; bi.iImage = 0; LPITEMIDLIST pIDL = SHBrowseForFolder(&bi); if (pIDL == NULL) return FALSE; TCHAR szDisplayName[MAX_PATH]; if (SHGetPathFromIDList(pIDL, szDisplayName)) { sSelectedFolder = szDisplayName; return TRUE; } return FALSE; } BOOL CDICOMSRVApp::PrepareFolder(CString& sFolder, LPCTSTR pszAlternativeName) { int iLength; sFolder.TrimLeft(); sFolder.TrimRight(); if (!sFolder.IsEmpty()) { iLength = sFolder.GetLength(); if (sFolder[iLength - 1] != '\\' && sFolder[iLength - 1] != '/') { sFolder += '\\'; } } if (::GetFileAttributes(sFolder) == INVALID_FILE_ATTRIBUTES) // Doesn't exist? { if (!::CreateDirectory(sFolder, NULL)) // Failed to create the folder? { // Use the alternative name if supplied CString sAlternativeName = pszAlternativeName; sAlternativeName.TrimLeft(); sAlternativeName.TrimRight(); if (!sAlternativeName.IsEmpty()) { sFolder = m_sApplicationFolder + sAlternativeName; iLength = sFolder.GetLength(); if (sFolder[iLength - 1] != '\\' && sFolder[iLength - 1] != '/') { sFolder += '\\'; } if (::GetFileAttributes(sFolder) == INVALID_FILE_ATTRIBUTES) // Doesn't exist? { if (!::CreateDirectory(sFolder, NULL)) { return FALSE; } } } else { return FALSE; } } } return TRUE; } BOOL CDICOMSRVApp::EmptyDatabase() const { CDatabase Database; try { Database.OpenEx(m_sConnectionString, CDatabase::noOdbcDialog); // Delete all the records in the Patients table CPatientRecordset PatientRecordset(&Database); PatientRecordset.Open(CRecordset::dynaset); while (!PatientRecordset.IsEOF()) { PatientRecordset.Delete(); PatientRecordset.MoveNext(); } PatientRecordset.Close(); // Delete all the records in the Studies table CStudyRecordset StudyRecordset(&Database); StudyRecordset.Open(CRecordset::dynaset); while (!StudyRecordset.IsEOF()) { StudyRecordset.Delete(); StudyRecordset.MoveNext(); } StudyRecordset.Close(); // Delete all the records in the Series table CSeriesRecordset SeriesRecordset(&Database); SeriesRecordset.Open(CRecordset::dynaset); while (!SeriesRecordset.IsEOF()) { SeriesRecordset.Delete(); SeriesRecordset.MoveNext(); } SeriesRecordset.Close(); // Delete all the records in the Images table CImageRecordset ImageRecordset(&Database); ImageRecordset.Open(CRecordset::dynaset); while (!ImageRecordset.IsEOF()) { ImageRecordset.Delete(); ImageRecordset.MoveNext(); } ImageRecordset.Close(); } catch(CDBException* pEx) { AfxMessageBox(pEx->m_strError, MB_OK | MB_ICONERROR); return FALSE; } catch(...) { return FALSE; } Database.Close(); return TRUE; } void CDICOMSRVApp::SaveSet(LDicomDS* pSet, BOOL bDataSet, BOOL bReceived, CString* pResultFile) const { if (pResultFile) *pResultFile = ""; if (!pSet) return; if (!bDataSet && bReceived) // A CS received by the server? { if (!m_bSaveReceivedCSs) return; } else if (bDataSet && bReceived) // A DS received by the server? { if (!m_bSaveReceivedDSs) return; } else if (bDataSet && !bReceived) // A DS sent out by the server? { if (!m_bSaveSentDSs) return; } else { return; } CString sPrefix = bDataSet ? "ds" : "cs"; sPrefix += bReceived ? "r" : "s"; TCHAR szFileName[MAX_PATH]; if (GetTempFileName(m_sLogFolder, sPrefix, 0, szFileName)) { CString sFileName = szFileName; int iIndex = sFileName.ReverseFind('.'); if (iIndex != -1) { sFileName = sFileName.Left(iIndex); sFileName += ".dcm"; // Save the Command or Data Set pSet->SaveDS(sFileName.GetBuffer(0), 0); if (pResultFile) { int nRevFind = sFileName.ReverseFind('\\'); *pResultFile = sFileName.Right(sFileName.GetLength() - nRevFind - 1); } } DeleteFile(szFileName); } } int CDICOMSRVApp::ExitInstance() { LBase::UnloadLibraries(LT_KRN | LT_DIS | LT_FIL | LT_IMG | LT_DLG); LDialogBase::Free (); return CWinApp::ExitInstance(); } L_VOID CDICOMSRVApp::GetCertName(LPCSTR pszFileName, CString& strCACertName)// To get the certificate names { char szpath[_MAX_PATH]; char szdrive[_MAX_PATH]; char szdir[_MAX_PATH]; GetModuleFileName(NULL, szpath, _MAX_PATH); _splitpath(szpath, szdrive, szdir, NULL, NULL ); strCACertName.Format("%s%s%s",szdrive,szdir,pszFileName); }