// DICOMSRVDlg.cpp : implementation file // #include "stdafx.h" #include "DICOMSRV.h" #include "server.h" #include "SRVDlg.h" #include #include "AdminDlg.h" #include "LogsDlg.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif void CALLBACK EXPORT TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime); extern CDICOMSRVApp theApp; ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDICOMSRVDlg dialog CDICOMSRVDlg::CDICOMSRVDlg(CWnd* pParent /*=NULL*/) : CDialog(CDICOMSRVDlg::IDD, pParent), m_SrvDicomDir(NULL, (L_CHAR*)(LPCTSTR) theApp.m_sTempFilesFolder), m_LEADDICOM1((L_CHAR*)(LPCTSTR) theApp.m_sTempFilesFolder), m_LEADDICOM2((L_CHAR*)(LPCTSTR) theApp.m_sTempFilesFolder), m_LEADTemp((L_CHAR*)(LPCTSTR) theApp.m_sTempFilesFolder) { //{{AFX_DATA_INIT(CDICOMSRVDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_Security = DICOM_SECURE_NONE; } void CDICOMSRVDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDICOMSRVDlg) DDX_Control(pDX, IDC_BUTTON_IMPORT, m_ButtonImport); DDX_Control(pDX, IDC_BUTTON_DELETE, m_ButtonDelete); DDX_Control(pDX, IDC_BUTTON_CLOSE, m_ButtonClose); DDX_Control(pDX, IDC_LIST2, m_EventLog); DDX_Control(pDX, IDC_LIST1, m_UserList); DDX_Control(pDX, IDC_TREE3, m_ConnectionList); DDX_Control(pDX, IDC_TREE2, m_KeyView); DDX_Control(pDX, IDC_TREE1, m_DicomDir); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDICOMSRVDlg, CDialog) //{{AFX_MSG_MAP(CDICOMSRVDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_COMMAND(ID_SERVER_EXIT, OnServerExit) ON_COMMAND(ID_SERVER_CONNECTIONS, OnServerConnections) ON_WM_CLOSE() ON_COMMAND(ID_SERVER_ADMINISTRATION, OnServerAdministration) ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, OnSelchangedTree1) ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1) ON_WM_TIMER() ON_COMMAND(ID_SERVER_LOGOPTIONS, OnServerLogOptions) ON_BN_CLICKED(IDC_BUTTON_IMPORT, OnButtonImport) ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDelete) ON_BN_CLICKED(IDC_BUTTON_CLOSE, OnButtonClose) ON_BN_CLICKED(IDC_CANCEL, OnCancel) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDICOMSRVDlg message handlers BOOL CDICOMSRVDlg::OnInitDialog() { short nRet; CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon m_bImport = FALSE; m_SrvDicomDir.ResetDicomDir(theApp.m_sImagesFolder); // Remove the Abstract and Transfer Syntaxes we don't support RemoveUnsupportedUIDs(); // image list CBitmap Bitmap; m_Image.Create(16, 16, ILC_MASK, 0, 2); Bitmap.LoadBitmap(IDB_BITMAP3); m_Image.Add(&Bitmap, (COLORREF)0xFFFFFF); Bitmap.DeleteObject(); Bitmap.LoadBitmap(IDB_BITMAP4); m_Image.Add(&Bitmap, (COLORREF)0xFFFFFF); Bitmap.DeleteObject(); Bitmap.LoadBitmap(IDB_BITMAP5); m_Image.Add(&Bitmap, (COLORREF)0xFFFFFF); Bitmap.DeleteObject(); m_ConnectionList.SetImageList(&m_Image, TVSIL_NORMAL); CRect rcStatus; rcStatus.SetRect(0,0,10,10); m_StatusBar1.Create(CCS_BOTTOM|CCS_NOMOVEY, rcStatus, this, IDC_STATUSBAR1); m_StatusBar1.ShowWindow(SW_SHOW); m_StatusBar1.GetWindowRect(&rcStatus); ScreenToClient(&rcStatus); CRect rcCtl; m_DicomDir.GetWindowRect(&rcCtl); ScreenToClient(&rcCtl); m_DicomDir.SetWindowPos(NULL, 0, 0, rcCtl.Width(), rcStatus.top - rcCtl.top, SWP_NOMOVE); m_KeyView.GetWindowRect(&rcCtl); ScreenToClient(&rcCtl); m_KeyView.SetWindowPos(NULL, 0, 0, rcCtl.Width(), rcStatus.top - rcCtl.top, SWP_NOMOVE); m_LEAD1hWnd = m_LEAD1.CreateWnd(this->m_hWnd, 0, WS_VISIBLE, rcCtl.left, rcCtl.top, rcCtl.Width(), rcStatus.top - rcCtl.top); ::ShowWindow(m_LEAD1hWnd, SW_HIDE); m_ButtonClose.ShowWindow(SW_HIDE); m_ConnectionList.ShowWindow(SW_HIDE); m_ConnectionList.GetWindowRect(&rcCtl); ScreenToClient(&rcCtl); m_ConnectionList.SetWindowPos(NULL, 0, 0, rcCtl.Width(), rcStatus.top - rcCtl.top, SWP_NOMOVE); m_UserList.InsertColumn(0, "User", LVCFMT_LEFT, -1, 0); m_UserList.InsertColumn(1, "IP", LVCFMT_LEFT, -1, 1); m_UserList.InsertColumn(2, "Port", LVCFMT_LEFT, -1, 2); m_UserList.InsertColumn(3, "Timeout", LVCFMT_LEFT, -1, 3); LoadClientsList(); m_EventLog.InsertColumn(0, "Date", LVCFMT_LEFT, 50, 0); m_EventLog.InsertColumn(1, "User", LVCFMT_LEFT, 50, 1); m_EventLog.InsertColumn(2, "Event", LVCFMT_LEFT, 50, 2); LoadEventsLog(); m_pDisplay = NULL; // Build the DICOM Directory from the database InitializeSrvDicomDir(); //display the data set DisplayDICOMDir(); //init server nRet = m_LEADDICOMServer.StartUp(); if(nRet != DICOM_SUCCESS) { MessageBox("Error starting server!", "Error", MB_OK); EndDialog(IDCANCEL); } nRet = m_LEADDICOMServer.Listen("", theApp.m_uServerPort, theApp.m_nMaxClients); if(nRet != DICOM_SUCCESS) { SetStatus("Error starting server!"); MessageBox("Error starting server!", "Error", MB_OK); EndDialog(IDCANCEL); } SetStatus("Server is Running"); LogEvent(theApp.m_sServerAETitle, "Server StartUp"); return TRUE; // return TRUE unless you set the focus to a control } L_CHAR* UnsupportedUIDs[] = { UID_PATIENT_ROOT_QUERY_GET, UID_STUDY_ROOT_QUERY_GET, UID_PATIENT_STUDY_QUERY_FIND, UID_PATIENT_STUDY_QUERY_MOVE, UID_PATIENT_STUDY_QUERY_GET, UID_MODALITY_WORKLIST_FIND, UID_MEDIA_STORAGE_DIRECTORY, UID_BASIC_STUDY_NOTIFICATION_CLASS, UID_STORAGE_COMMITMENT_PUSH_MODEL_CLASS, UID_STORAGE_COMMITMENT_PUSH_MODEL_INSTANCE, UID_STORAGE_COMMITMENT_PULL_MODEL_CLASS, UID_STORAGE_COMMITMENT_PULL_MODEL_INSTANCE, UID_DETACHED_PATIENT_CLASS, UID_DETACHED_PATIENT_META_CLASS, UID_DETACHED_VISIT_CLASS, UID_DETACHED_STUDY_CLASS, UID_STUDY_COMPONENT_CLASS, UID_MODALITY_PERFORMED_CLASS, UID_MODALITY_PERFORMED_RETRIEVE_CLASS, UID_MODALITY_PERFORMED_NOTIFICATION_CLASS, UID_DETACHED_RESULTS_CLASS, UID_DETACHED_RESULTS_META_CLASS, UID_DETACHED_STUDY_META_CLASS, UID_DETACHED_INTERPRETATION_CLASS, UID_BASIC_FILM_SESSION_CLASS, UID_BASIC_FILM_BOX_CLASS, UID_BASIC_GRAYSCALE_IMAGE_BOX_CLASS, UID_BASIC_COLOR_IMAGE_BOX_CLASS, UID_REFERENCED_IMAGE_BOX_CLASS_RETIRED, UID_BASIC_GRAYSCALE_PRINT_META_CLASS, UID_REFERENCED_GRAYSCALE_PRINT_META_CLASS_RETIRED, UID_PRINT_JOB_CLASS, UID_BASIC_ANNOTATION_BOX_CLASS, UID_PRINTER_CLASS, UID_PRINTER_INSTANCE, UID_BASIC_COLOR_PRINT_META_CLASS, UID_REFERENCED_COLOR_PRINT_META_CLASS_RETIRED, UID_VOI_LUT_BOX_CLASS_RETIRED, UID_PRESENTATION_LUT_CLASS, UID_IMAGE_OVERLAY_BOX_CLASS_RETIRED, UID_PRINT_QUEUE_INSTANCE, UID_PRINT_QUEUE_CLASS, UID_STORED_PRINT_STORAGE_CLASS, UID_HARDCOPY_GRAYSCALE_IMAGE_STORAGE_CLASS, UID_HARDCOPY_COLOR_IMAGE_STORAGE_CLASS, UID_PULL_PRINT_REQUEST_CLASS, UID_PULL_STORED_PRINT_META_CLASS, UID_GE_MR_IMAGE, UID_GE_CT_IMAGE, UID_GE_DISPLAY_IMAGERMATION, UID_GE_ARM_MIGRATION, UID_GE_ARM_MIGRATION_INSTANCE, UID_JPEG_EXTENDED_3_5, UID_JPEG_SPECTRAL_NONHIER_6_8, UID_JPEG_SPECTRAL_NONHIER_7_9, UID_JPEG_FULL_NONHIER_10_12, UID_JPEG_FULL_NONHIER_11_13, UID_JPEG_LOSSLESS_NONHIER_15, UID_JPEG_EXTENDED_HIER_16_18, UID_JPEG_EXTENDED_HIER_17_19, UID_JPEG_SPECTRAL_HIER_20_22, UID_JPEG_SPECTRAL_HIER_21_23, UID_JPEG_FULL_HIER_24_26, UID_JPEG_FULL_HIER_25_27, UID_JPEG_LOSSLESS_HIER_PROCESS_28, UID_JPEG_LOSSLESS_HIER_PROCESS_29, UID_JPEG_LS_LOSSLESS, UID_JPEG_LS_LOSSY }; void CDICOMSRVDlg::RemoveUnsupportedUIDs() { pDICOMUID pUID; int iSize = sizeof(UnsupportedUIDs) / sizeof(UnsupportedUIDs[0]); for (int i = 0; i < iSize; i++) { pUID = LDicomUID::Find(UnsupportedUIDs[i]); if (pUID) LDicomUID::Delete(pUID); } } void CDICOMSRVDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CDICOMSRVDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CDICOMSRVDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CDICOMSRVDlg::OnServerExit() { if(Unload()) EndDialog(IDOK); } void CDICOMSRVDlg::OnServerConnections() { CMenu *pMenu=NULL; pMenu = GetMenu(); UINT uState = pMenu->GetMenuState(ID_SERVER_CONNECTIONS, MF_BYCOMMAND|MF_CHECKED); if(uState&MF_CHECKED) { m_ButtonClose.ShowWindow(SW_HIDE); m_ConnectionList.ShowWindow(SW_HIDE); m_ButtonImport.ShowWindow(SW_SHOW); m_ButtonDelete.ShowWindow(SW_SHOW); m_DicomDir.ShowWindow(SW_SHOW); if(m_LEAD1.IsAllocated()) ::ShowWindow(m_LEAD1hWnd, SW_SHOW); else m_KeyView.ShowWindow(SW_SHOW); pMenu->CheckMenuItem(ID_SERVER_CONNECTIONS, MF_BYCOMMAND|MF_UNCHECKED); } else { m_ButtonClose.ShowWindow(SW_SHOW); m_ConnectionList.ShowWindow(SW_SHOW); m_ButtonImport.ShowWindow(SW_HIDE); m_ButtonDelete.ShowWindow(SW_HIDE); m_KeyView.ShowWindow(SW_HIDE); m_DicomDir.ShowWindow(SW_HIDE); ::ShowWindow(m_LEAD1hWnd, SW_HIDE); pMenu->CheckMenuItem(ID_SERVER_CONNECTIONS, MF_BYCOMMAND|MF_CHECKED); } } void CDICOMSRVDlg::LoadClientsList() { m_UserList.DeleteAllItems(); CStdioFile StdioFile; if (!StdioFile.Open(theApp.m_sApplicationFolder + CLIENTS_LIST_FILENAME, CFile::modeRead | CFile::typeText)) { return; } CString sClient; CString sAETitle; CString sIPAddress; CString sPortNumber; CString sTimeout; int nPos; LV_ITEM lvi; try { while (StdioFile.ReadString(sClient)) { sAETitle = ""; sIPAddress = ""; sPortNumber = "0"; sTimeout = "0"; nPos = sClient.Find(','); if (nPos != -1) { sAETitle = sClient.Mid(0, nPos); } sClient = sClient.Right(sClient.GetLength() - (nPos + 1)); nPos = sClient.Find(','); if (nPos != -1) { sIPAddress = sClient.Mid(0, nPos); } sClient = sClient.Right(sClient.GetLength() - (nPos + 1)); nPos = sClient.Find(','); if (nPos != -1) { sPortNumber = sClient.Mid(0, nPos); } sClient = sClient.Right(sClient.GetLength() - (nPos + 1)); if (sClient.GetLength()) { sTimeout = sClient; } nPos = m_UserList.InsertItem(m_UserList.GetItemCount(), sAETitle); if (nPos != -1) { lvi.mask = LVIF_TEXT; lvi.iItem = nPos; lvi.iSubItem = 1; lvi.pszText = sIPAddress.GetBuffer(0); m_UserList.SetItem(&lvi); lvi.iSubItem = 2; lvi.pszText = sPortNumber.GetBuffer(0); m_UserList.SetItem(&lvi); lvi.iSubItem = 3; lvi.pszText = sTimeout.GetBuffer(0); m_UserList.SetItem(&lvi); } } } catch(...) { return; } } void CDICOMSRVDlg::LoadEventsLog() { if (!theApp.m_bGenerateEventsLogFile) { return; } m_EventLog.DeleteAllItems(); CStdioFile StdioFile; if (!StdioFile.Open(theApp.m_sApplicationFolder + EVENTS_LOG_FILENAME, CFile::modeRead | CFile::typeText)) { return; } CString sEvent; CString sDate; CString sClient; CString sEventDesc; int nPos; LV_ITEM lvi; try { while (StdioFile.ReadString(sEvent)) { sDate = ""; sClient = ""; sEventDesc = ""; nPos = sEvent.Find(','); if (nPos != -1) { sDate = sEvent.Mid(0, nPos); } sEvent = sEvent.Right(sEvent.GetLength() - (nPos + 1)); nPos = sEvent.Find(','); if (nPos != -1) { sClient = sEvent.Mid(0, nPos); } sEventDesc = sEvent.Right(sEvent.GetLength() - (nPos + 1)); nPos = m_EventLog.InsertItem(m_EventLog.GetItemCount(), sDate); if (nPos != -1) { lvi.mask = LVIF_TEXT; lvi.iItem = nPos; lvi.iSubItem = 1; lvi.pszText = sClient.GetBuffer(0); m_EventLog.SetItem(&lvi); lvi.iSubItem = 2; lvi.pszText = sEventDesc.GetBuffer(0); m_EventLog.SetItem(&lvi); } } } catch(...) { return; } } void CDICOMSRVDlg::SetStatus(CString szStatus) { m_StatusBar1.SetWindowText(szStatus); } void CDICOMSRVDlg::LogEvent(CString szUser, CString szEvent) { CTime theTime = CTime::GetCurrentTime(); CString szDate = theTime.Format("%m/%d/%Y %I:%M:%S %p"); int nPos; nPos = m_EventLog.InsertItem(m_EventLog.GetItemCount(), szDate); if(nPos!=-1) { LV_ITEM lvi; lvi.mask = LVIF_TEXT; lvi.iItem = nPos; lvi.iSubItem = 1; lvi.pszText = szUser.GetBuffer(szUser.GetLength()+1); szUser.ReleaseBuffer(); m_EventLog.SetItem(&lvi); lvi.iSubItem = 2; lvi.pszText = szEvent.GetBuffer(szEvent.GetLength()+1); szEvent.ReleaseBuffer(); m_EventLog.SetItem(&lvi); } //write info to logfile } BOOL CDICOMSRVDlg::Unload() { if (m_LEADDICOMServer.GetClientCount() > 0) { int nRet = MessageBox("There are clients connected!\nDo you wish to shutdown?", "Warning", MB_YESNO); if (nRet != IDYES) return FALSE; } KillTimer(CLIENTS_TIMER_ID); CClientData* pClientData; HTREEITEM hItem = m_ConnectionList.GetRootItem(); while (hItem) { pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); pClientData->m_pClient->CloseForced(TRUE); delete pClientData; hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } m_LEADDICOMServer.ShutDown(); LogEvent(theApp.m_sServerAETitle, "Server Shutdown"); if (!theApp.SaveServerSettings()) { MessageBox("Failed to save the server settings.", "Error", MB_OK | MB_ICONERROR); } if (!SaveClientsList()) { MessageBox("Failed to save the list of clients.", "Error", MB_OK | MB_ICONERROR); } if (!SaveEventsLog()) { MessageBox("Failed to save the events log file.", "Error", MB_OK | MB_ICONERROR); } return TRUE; } void CDICOMSRVDlg::OnClose() { if (Unload()) { CDialog::OnCancel(); } } BOOL CDICOMSRVDlg::SaveClientsList() { CStdioFile StdioFile; if (!StdioFile.Open(theApp.m_sApplicationFolder + CLIENTS_LIST_FILENAME, CFile::modeCreate | CFile::modeWrite | CFile::typeText)) { return FALSE; } LV_ITEM lvi; TCHAR szBuffer[1024]; CString sClient; CString sAETitle; CString sIPAddress; CString sPortNumber; CString sTimeout; lvi.mask = LVIF_TEXT; lvi.pszText = szBuffer; lvi.cchTextMax = sizeof(szBuffer) / sizeof(TCHAR); int iItemCount = m_UserList.GetItemCount(); for (int i = 0; i < iItemCount; i++) { lvi.iItem = i; sAETitle = ""; sIPAddress = ""; sPortNumber = ""; sTimeout = ""; lvi.iSubItem = 0; if (m_UserList.GetItem(&lvi)) { sAETitle = szBuffer; lvi.iSubItem = 1; if (m_UserList.GetItem(&lvi)) { sIPAddress = szBuffer; } lvi.iSubItem = 2; if (m_UserList.GetItem(&lvi)) { sPortNumber = szBuffer; } lvi.iSubItem = 3; if (m_UserList.GetItem(&lvi)) { sTimeout = szBuffer; } } sClient = sAETitle + "," + sIPAddress + "," + sPortNumber + "," + sTimeout + "\n"; try { StdioFile.WriteString(sClient); } catch(...) { return FALSE; } } return TRUE; } BOOL CDICOMSRVDlg::SaveEventsLog() { if (!theApp.m_bGenerateEventsLogFile) { return TRUE; } CStdioFile StdioFile; if (!StdioFile.Open(theApp.m_sApplicationFolder + EVENTS_LOG_FILENAME, CFile::modeCreate | CFile::modeWrite | CFile::typeText)) { return FALSE; } LV_ITEM lvi; TCHAR szBuffer[1024]; CString sEvent; CString sDate; CString sClient; CString sEventDesc; lvi.mask = LVIF_TEXT; lvi.pszText = szBuffer; lvi.cchTextMax = sizeof(szBuffer) / sizeof(TCHAR); int iItemCount = m_EventLog.GetItemCount(); for (int i = 0; i < iItemCount; i++) { lvi.iItem = i; sDate = ""; sClient = ""; sEventDesc = ""; lvi.iSubItem = 0; if (m_EventLog.GetItem(&lvi)) { sDate = szBuffer; lvi.iSubItem = 1; if (m_EventLog.GetItem(&lvi)) { sClient = szBuffer; } lvi.iSubItem = 2; if (m_EventLog.GetItem(&lvi)) { sEventDesc = szBuffer; } } sEvent = sDate + "," + sClient + "," + sEventDesc + "\n"; try { StdioFile.WriteString(sEvent); } catch(...) { return FALSE; } } return TRUE; } void CDICOMSRVDlg::OnServerAdministration() { CAdminDlg AdminDlg; BOOL bRestart; if (m_LEADDICOMServer.GetClientCount() > 0) { MessageBox("Cannot change server settings, clients are connected!", "Warning", MB_OK); AdminDlg.m_bEnableEditing = FALSE; bRestart = FALSE; } else { m_LEADDICOMServer.Close(); SetStatus("Server was Stopped"); LogEvent(theApp.m_sServerAETitle, "Server Shutdown"); bRestart = TRUE; } AdminDlg.m_pUserList = &m_UserList; AdminDlg.m_pEventLog = &m_EventLog; AdminDlg.m_SecureMode = m_Security; AdminDlg.m_sServerAETitle = theApp.m_sServerAETitle; AdminDlg.m_uServerPort = theApp.m_uServerPort; AdminDlg.m_nTimeOut = theApp.m_nTimeOut; AdminDlg.m_nMaxClients = theApp.m_nMaxClients; if (AdminDlg.DoModal() == IDOK) { m_Security = AdminDlg.m_SecureMode; theApp.m_sServerAETitle = AdminDlg.m_sServerAETitle; theApp.m_uServerPort = AdminDlg.m_uServerPort; theApp.m_nTimeOut = AdminDlg.m_nTimeOut; theApp.m_nMaxClients = AdminDlg.m_nMaxClients; } if (bRestart) // Restart server { L_INT nRet = m_LEADDICOMServer.Listen("", theApp.m_uServerPort, theApp.m_nMaxClients); if (nRet != DICOM_SUCCESS) MessageBox("Error starting server!", "Error", MB_OK); else { SetStatus("Server was Restarted"); LogEvent(theApp.m_sServerAETitle, "Server StartUp"); } } } BEGIN_EVENTSINK_MAP(CDICOMSRVDlg, CDialog) //{{AFX_EVENTSINK_MAP(CDICOMSRVDlg) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() BOOL CDICOMSRVDlg::FindClient(const CString& sIPAddress, const CString* psAETitle, int* piUserListIndex) { int iCount = m_UserList.GetItemCount(); for (int i = 0; i < iCount; i++) { if (sIPAddress == m_UserList.GetItemText(i, 1)) { if (psAETitle) { if (psAETitle->CompareNoCase(m_UserList.GetItemText(i, 0)) == 0) { if (piUserListIndex) *piUserListIndex = i; return TRUE; } } else { if (piUserListIndex) *piUserListIndex = i; return TRUE; } } } return FALSE; } void CDICOMSRVDlg::SetClientInfo(CNetClient* pClient, const CString& sIPAddress, const CString& sAETitle) { CClientData* pClientData; HTREEITEM hItem = m_ConnectionList.GetRootItem(); while (hItem) { pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); if (pClientData->m_pClient == pClient) { int iUserListIndex; if (FindClient(sIPAddress, &sAETitle, &iUserListIndex)) { pClientData->m_sAETitle = m_UserList.GetItemText(iUserListIndex, 0); pClientData->m_uTimeout = atoi(m_UserList.GetItemText(iUserListIndex, 3)); m_ConnectionList.SetItemText(m_ConnectionList.GetChildItem(hItem), "Remote AE: " + pClientData->m_sAETitle); } return; } hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } } BOOL CDICOMSRVDlg::GetClientInfo(CNetClient* pClient, CString& sAETitle) { CClientData* pClientData; HTREEITEM hItem = m_ConnectionList.GetRootItem(); while (hItem) { pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); if (pClientData->m_pClient == pClient) { sAETitle = pClientData->m_sAETitle; return TRUE; } hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } return FALSE; } void CDICOMSRVDlg::DisplayAssociate(CNetClient *pClient, LDicomAssociate *pPDU) { L_INT32 x; CString szOut; CString szTest; CString szTemp; L_UCHAR nID; CString szAbstract; L_INT32 lCount; L_INT32 y; CString szTransfer; CString szClass; CString szVersion; HTREEITEM hItem=NULL; HTREEITEM hChild=NULL; HTREEITEM hChildNode=NULL; HTREEITEM hTemp=NULL; pDICOMUID pUID=NULL; hItem = m_ConnectionList.GetRootItem(); while (hItem) { if (((CClientData*) m_ConnectionList.GetItemData(hItem))->m_pClient == pClient) break; hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } if (!hItem) return; hChild = m_ConnectionList.InsertItem("Association:", 1, 1, hItem); szOut.Format("%d", pPDU->GetVersion()); //display version hChildNode = m_ConnectionList.InsertItem("Version: " + szOut, 2, 2, hChild); szTemp = pPDU->GetCalled(); //display called application szOut = "Called: " + szTemp; hChildNode = m_ConnectionList.InsertItem(szOut, 2, 2, hChild); szTemp = pPDU->GetCalling(); //display calling application szOut = "Calling: " + szTemp; hChildNode = m_ConnectionList.InsertItem(szOut, 2, 2, hChild); szTest = pPDU->GetApplication(); pUID = LDicomUID::Find(pPDU->GetApplication()); if(pUID) { szTemp = pUID->pszName; szOut = "Application Context: " + szTemp + " - " + szTest; //display application context } else szOut = "Application Context: " + szTest; //display application context hChildNode = m_ConnectionList.InsertItem(szOut, 2, 2, hChild); //get each Presentation Context for(x=0; xGetPresentationCount(); x++) { nID = pPDU->GetPresentation(x); switch(pPDU->GetResult(nID)) { case PDU_ACCEPT_RESULT_SUCCESS: szOut = "Acceptance"; break; case PDU_ACCEPT_RESULT_USER_REJECT: szOut = "User Rejection"; break; case PDU_ACCEPT_RESULT_PROVIDER_REJECT: szOut = "Provider Rejection"; break; case PDU_ACCEPT_RESULT_ABSTRACT_SYNTAX: szOut = "Abstract Syntax Not Supported"; break; case PDU_ACCEPT_RESULT_TRANSFER_SYNTAX: szOut = "Transfer Syntax(es) Not Supported"; break; default: szTemp.Format("%ld", pPDU->GetResult(nID)); szOut = "Unknown Reason - " + szTemp; break; } szTemp.Format("%d", nID); hChildNode = m_ConnectionList.InsertItem("ID: " + szTemp + " - " + szOut, 2, 2, hChild); //each Presentation Context can have one Abstract Syntax szAbstract = pPDU->GetAbstract(nID); if(szAbstract.GetLength() > 0) { pUID = LDicomUID::Find(pPDU->GetAbstract(nID)); if(pUID) { szTemp = pUID->pszName; szOut = "Abstract Syntax: " + szTemp + " - " + szAbstract; } else szOut = "Abstract Syntax: " + szAbstract; m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } //each Presentation Context can have one or more Transfer Syntax(es) lCount = pPDU->GetTransferCount(nID); if(lCount > 0) { for(y=0; yGetTransfer(nID, y); if(szTransfer.GetLength() > 0) { pUID = LDicomUID::Find(pPDU->GetTransfer(nID, y)); if(pUID) { szTemp = pUID->pszName; szOut = "Transfer Syntax: " + szTemp + " - " + szTransfer; } else szOut = "Transfer Syntax: " + szTransfer; m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } } } } szOut = "User Information"; hChildNode = m_ConnectionList.InsertItem(szOut, 2, 2, hChild); if(pPDU->IsMaxLength()) { szTemp.Format("%ld", pPDU->GetMaxLength()); szOut = "Maximum Length = " + szTemp; m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } if(pPDU->IsImplementClass()) { szClass = pPDU->GetImplementClass(); pUID = LDicomUID::Find(pPDU->GetImplementClass()); if(pUID) { szTemp = pUID->pszName; szOut = "Implementation Class: " + szTemp + " - " + szClass; } else szOut = "Implementation Class: " + szClass; m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } if(pPDU->IsAsyncOperations()) { szOut = "Asynchronous Operations"; hTemp = m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); szTemp.Format("%ld", pPDU->GetInvokedOperations()); szOut = "Invoked Operations: " + szTemp; m_ConnectionList.InsertItem(szOut, 2, 2, hTemp); szTemp.Format("%ld", pPDU->GetPerformedOperations()); szOut = "Performed Operations: " + szTemp; m_ConnectionList.InsertItem(szOut, 2, 2, hTemp); } if(pPDU->IsImplementVersion()) { szVersion = pPDU->GetImplementVersion(); szOut = "Implementation Version: " + szVersion; m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } lCount = pPDU->GetUserInfoCount(); if(lCount > 0) { for(y=0; yGetTypeUserInfo(y), pPDU->GetLengthUserInfo(y)); m_ConnectionList.InsertItem(szOut, 2, 2, hChildNode); } } } void CDICOMSRVDlg::LastClientAction(CNetClient *pClient, CString szAction, BOOL bMessage) { HTREEITEM hItem=NULL; CString szTemp; hItem = m_ConnectionList.GetRootItem(); while(hItem) { if (((CClientData*) m_ConnectionList.GetItemData(hItem))->m_pClient == pClient) break; hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } if (!hItem) return; hItem = m_ConnectionList.GetNextItem(hItem, TVGN_CHILD); hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); if (bMessage) { long count; count = m_ConnectionList.GetItemData(hItem) + 1; m_ConnectionList.SetItemData(hItem, count); szTemp.Format("Number of Messages: %ld", count); m_ConnectionList.SetItemText(hItem, szTemp); } hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); m_ConnectionList.SetItemText(hItem, "Last Action: " + szAction); } void CDICOMSRVDlg::EnableClientTimeout(CNetClient* pClient, BOOL bEnable) { CClientData* pClientData; HTREEITEM hItem = m_ConnectionList.GetRootItem(); while (hItem) { pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); if (pClientData->m_pClient == pClient) { pClientData->m_bEnableTimeout = bEnable && pClientData->m_uTimeout; pClientData->m_uSecondsElapsed = 0; return; } hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } } void CDICOMSRVDlg::OnButtonClose() { HTREEITEM hItem=NULL; hItem = m_ConnectionList.GetSelectedItem(); if (!hItem) return; if (MessageBox("Forcefully close client?", "Warning", MB_YESNO) == IDYES) { CClientData* pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); // Send Abort pClientData->m_pClient->SendAbort(PDU_ABORT_SOURCE_PROVIDER, PDU_ABORT_REASON_UNKNOWN); // Close client pClientData->m_pClient->Close(); // Remove from list m_ConnectionList.DeleteItem(hItem); delete pClientData; } } void CDICOMSRVDlg::DisplayDICOMDir() { pDICOMELEMENT pKey=NULL; m_DicomDir.DeleteAllItems(); m_KeyView.DeleteAllItems(); m_LEAD1.Free(); pKey = m_SrvDicomDir.GetFirstKey(NULL, FALSE); if(pKey) pKey = m_SrvDicomDir.GetRootKey(pKey); if(pKey) DisplayDirDS(pKey, NULL, FALSE); } void CDICOMSRVDlg::DisplayDirDS(pDICOMELEMENT pElement, HTREEITEM hParent, BOOL bChild) { HTREEITEM hItem=NULL; pDICOMELEMENT pChild=NULL; pDICOMELEMENT pNext=NULL; hItem = DisplayDSKey(pElement, hParent, bChild); //try children pChild = m_SrvDicomDir.GetChildKey(pElement); if(pChild) { DisplayDirDS(pChild, hItem, TRUE); //recurse } //try next pNext = m_SrvDicomDir.GetNextKey(pElement, TRUE); while(pNext) { hItem = DisplayDSKey(pNext, hParent, bChild); pChild = m_SrvDicomDir.GetChildKey(pNext); if(pChild) { DisplayDirDS(pChild, hItem, TRUE); //recurse } pNext = m_SrvDicomDir.GetNextKey(pNext, TRUE); } } HTREEITEM CDICOMSRVDlg::DisplayDSKey(pDICOMELEMENT pKey, HTREEITEM hParent, BOOL bChild) { CString szKey; HTREEITEM hItem=NULL; CString szOut; pDICOMELEMENT pElement=NULL; pDICOMELEMENT pTemp=NULL; L_CHAR L_FAR *pVal=NULL; L_UINT32 lSize; //display key szKey = m_SrvDicomDir.GetValueKey(pKey); szOut = ""; if(szKey == "PATIENT") { pTemp = m_SrvDicomDir.GetChildElement(pKey, FALSE); pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_PATIENT_NAME, TRUE); if(!pElement) pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_PATIENT_ID, TRUE); if(pElement) { lSize = m_SrvDicomDir.GetConvertValue(pElement, NULL); pVal = (L_CHAR L_FAR*)GlobalAllocPtr(GMEM_MOVEABLE, lSize*sizeof(L_CHAR)); if(pVal) { m_SrvDicomDir.GetConvertValue(pElement, pVal); szOut = pVal; GlobalFreePtr(pVal); } } } else if(szKey == "STUDY") { pTemp = m_SrvDicomDir.GetChildElement(pKey, FALSE); pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_STUDY_ID, TRUE); if(!pElement) pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_STUDY_INSTANCE_UID, TRUE); if(pElement) { lSize = m_SrvDicomDir.GetConvertValue(pElement, NULL); pVal = (L_CHAR L_FAR*)GlobalAllocPtr(GMEM_MOVEABLE, lSize*sizeof(L_CHAR)); if(pVal) { m_SrvDicomDir.GetConvertValue(pElement, pVal); szOut = pVal; GlobalFreePtr(pVal); } } } else if(szKey == "SERIES") { pTemp = m_SrvDicomDir.GetChildElement(pKey, FALSE); pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_SERIES_NUMBER, TRUE); if(!pElement) pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_SERIES_INSTANCE_UID, TRUE); if(pElement) { lSize = m_SrvDicomDir.GetConvertValue(pElement, NULL); pVal = (L_CHAR L_FAR*)GlobalAllocPtr(GMEM_MOVEABLE, lSize*sizeof(L_CHAR)); if(pVal) { m_SrvDicomDir.GetConvertValue(pElement, pVal); szOut = pVal; GlobalFreePtr(pVal); } } } else if(szKey == "IMAGE") { pTemp = m_SrvDicomDir.GetChildElement(pKey, FALSE); pElement = m_SrvDicomDir.FindFirstElement(pTemp, TAG_INSTANCE_NUMBER, TRUE); if(pElement) { lSize = m_SrvDicomDir.GetConvertValue(pElement, NULL); pVal = (L_CHAR L_FAR*)GlobalAllocPtr(GMEM_MOVEABLE, lSize*sizeof(L_CHAR)); if(pVal) { m_SrvDicomDir.GetConvertValue(pElement, pVal); szOut = pVal; GlobalFreePtr(pVal); } } } else return(NULL); if(!hParent) hItem = m_DicomDir.InsertItem(szKey + "-" + szOut); else if(!bChild) hItem = m_DicomDir.InsertItem(szKey + "-" + szOut, m_DicomDir.GetNextItem(hParent, TVGN_PARENT)); else hItem = m_DicomDir.InsertItem(szKey + "-" + szOut, hParent); m_DicomDir.SetItemData(hItem, (long)pKey); return(hItem); } void CDICOMSRVDlg::InitializeSrvDicomDir() { CDatabase Database; Database.OpenEx(theApp.m_sConnectionString, CDatabase::noOdbcDialog); CImageRecordset ImageRecordset(&Database); ImageRecordset.Open(CRecordset::dynaset, _T("SELECT ReferencedFile FROM Images")); CDBVariant varReferencedFile; while (!ImageRecordset.IsEOF()) { ImageRecordset.GetFieldValue("ReferencedFile", varReferencedFile); if (varReferencedFile.m_dwType == DBVT_STRING) { m_SrvDicomDir.InsertDicomFile((L_CHAR*)(LPCTSTR) (theApp.m_sImagesFolder + *varReferencedFile.m_pstring)); } ImageRecordset.MoveNext(); } ImageRecordset.Close(); Database.Close(); } // Possible return values: (0: Success), (1: Failure), (2: Already exists) L_INT CDICOMSRVDlg::InsertDataSet(LDicomDS *pSourceDS, CString szFile) { pDICOMELEMENT pElement; // Patient ID CString sPatientID; pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_ID, FALSE); if (!pElement) return 1; sPatientID = pSourceDS->GetStringValue(pElement, 0, 1); // Patient Name CString sPatientName; pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_NAME, FALSE); if (pElement) sPatientName = pSourceDS->GetStringValue(pElement, 0, 1); // Study Instance UID CString sStudyInstanceUID; pElement = pSourceDS->FindFirstElement(NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (!pElement) return 1; sStudyInstanceUID = pSourceDS->GetStringValue(pElement, 0, 1); // Series Instance UID CString sSeriesInstanceUID; pElement = pSourceDS->FindFirstElement(NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (!pElement) return 1; sSeriesInstanceUID = pSourceDS->GetStringValue(pElement, 0, 1); // SOP Instance UID CString sSOPInstanceUID; pElement = pSourceDS->FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); if (!pElement) return 1; sSOPInstanceUID = pSourceDS->GetStringValue(pElement, 0, 1); // SOP Class UID CString sSOPClassUID; pElement = pSourceDS->FindFirstElement(NULL, TAG_SOP_CLASS_UID, FALSE); if (!pElement) { pElement = pSourceDS->FindFirstElement(NULL, TAG_MEDIA_STORAGE_SOP_CLASS_UID, FALSE); } if (pElement) { sSOPClassUID = pSourceDS->GetStringValue(pElement, 0, 1); } if (sSOPClassUID.IsEmpty()) { sSOPClassUID = "1.1.1.1"; } // Transfer Syntax UID CString sTransferSyntaxUID; pElement = pSourceDS->FindFirstElement(NULL, TAG_TRANSFER_SYNTAX_UID, FALSE); if (pElement) { sTransferSyntaxUID = pSourceDS->GetStringValue(pElement, 0, 1); } if (sTransferSyntaxUID.IsEmpty()) { sTransferSyntaxUID = UID_IMPLICIT_VR_LITTLE_ENDIAN; } CDatabase Database; try { Database.OpenEx(theApp.m_sConnectionString, CDatabase::noOdbcDialog); } catch(...) { return 1; } CString sQuery; pVALUEDATE pDate; pVALUETIME pTime; L_INT nRet = 2; try { // Does this Patient already exist? sQuery = "SELECT * FROM Patients WHERE PatientID = '" + sPatientID + "';"; CPatientRecordset rstPatient(&Database); rstPatient.Open(CRecordset::dynaset, sQuery); if (rstPatient.IsEOF()) // Add Patient { // Add a new record rstPatient.AddNew(); rstPatient.m_PatientID = sPatientID; rstPatient.m_PatientName = sPatientName; // PatientBirthDate pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_BIRTH_DATE, FALSE); if (pElement) { pDate = pSourceDS->GetDateValue(pElement, 0, 1); if(IsValidDate(pDate)) { memset(&rstPatient.m_PatientBirthDate, 0, sizeof(TIMESTAMP_STRUCT)); rstPatient.m_PatientBirthDate.year = pDate->nYear; rstPatient.m_PatientBirthDate.month = pDate->nMonth; rstPatient.m_PatientBirthDate.day = pDate->nDay; } } // PatientBirthTime pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_BIRTH_TIME, FALSE); if (pElement) { pTime = pSourceDS->GetTimeValue(pElement, 0, 1); if(IsValidTime(pTime)) { memset(&rstPatient.m_PatientBirthTime, 0, sizeof(TIMESTAMP_STRUCT)); rstPatient.m_PatientBirthTime.year = 9999; rstPatient.m_PatientBirthTime.month = 1; rstPatient.m_PatientBirthTime.day = 1; rstPatient.m_PatientBirthTime.hour = pTime->nHours; rstPatient.m_PatientBirthTime.minute = pTime->nMinutes; rstPatient.m_PatientBirthTime.second = pTime->nSeconds; } } // PatientSex pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_SEX, FALSE); if (pElement) rstPatient.m_PatientSex = pSourceDS->GetStringValue(pElement, 0, 1); // EthnicGroup pElement = pSourceDS->FindFirstElement(NULL, TAG_ETHNIC_GROUP, FALSE); if (pElement) rstPatient.m_EthnicGroup = pSourceDS->GetStringValue(pElement, 0, 1); // PatientComments pElement = pSourceDS->FindFirstElement(NULL, TAG_PATIENT_COMMENTS, FALSE); if (pElement) rstPatient.m_PatientComments = pSourceDS->GetStringValue(pElement, 0, 1); rstPatient.Update(); nRet = 0; } rstPatient.Close(); // Does this Study already exist? sQuery = "SELECT * FROM Studies WHERE PatientID = '" + sPatientID + "' AND StudyInstanceUID = '" + sStudyInstanceUID + "';"; CStudyRecordset rstStudy(&Database); rstStudy.Open(CRecordset::dynaset, sQuery); if (rstStudy.IsEOF()) // Add Study { // Add a new record rstStudy.AddNew(); // StudyInstanceUID rstStudy.m_StudyInstanceUID = sStudyInstanceUID; // StudyDate pElement = pSourceDS->FindFirstElement(NULL, TAG_STUDY_DATE, FALSE); if (pElement) { pDate = pSourceDS->GetDateValue(pElement, 0, 1); if (IsValidDate(pDate)) { memset(&rstStudy.m_StudyDate, 0, sizeof(TIMESTAMP_STRUCT)); rstStudy.m_StudyDate.year = pDate->nYear; rstStudy.m_StudyDate.month = pDate->nMonth; rstStudy.m_StudyDate.day = pDate->nDay; } } // StudyTime pElement = pSourceDS->FindFirstElement(NULL, TAG_STUDY_TIME, FALSE); if (pElement) { pTime = pSourceDS->GetTimeValue(pElement, 0, 1); if (IsValidTime(pTime)) { memset(&rstStudy.m_StudyTime, 0, sizeof(TIMESTAMP_STRUCT)); rstStudy.m_StudyTime.year = 9999; rstStudy.m_StudyTime.month = 1; rstStudy.m_StudyTime.day = 1; rstStudy.m_StudyTime.hour = pTime->nHours; rstStudy.m_StudyTime.minute = pTime->nMinutes; rstStudy.m_StudyTime.second = pTime->nSeconds; } } // AccessionNumber pElement = pSourceDS->FindFirstElement(NULL, TAG_ACCESSION_NUMBER, FALSE); if (pElement) rstStudy.m_AccessionNumber = pSourceDS->GetStringValue(pElement, 0, 1); // StudyID pElement = pSourceDS->FindFirstElement(NULL, TAG_STUDY_ID, FALSE); if (pElement) rstStudy.m_StudyID = pSourceDS->GetStringValue(pElement, 0, 1); // PatientName rstStudy.m_PatientName = sPatientName; // PatientID rstStudy.m_PatientID = sPatientID; // StudyDescription pElement = pSourceDS->FindFirstElement(NULL, TAG_STUDY_DESCRIPTION, FALSE); if (pElement) rstStudy.m_StudyDescription = pSourceDS->GetStringValue(pElement, 0, 1); rstStudy.Update(); nRet = 0; } rstStudy.Close(); // Does this Series already exist? sQuery = "SELECT * FROM Series where StudyInstanceUID = '" + sStudyInstanceUID + "' AND SeriesInstanceUID = '" + sSeriesInstanceUID + "';"; CSeriesRecordset rstSeries(&Database); rstSeries.Open(CRecordset::dynaset, sQuery); if (rstSeries.IsEOF()) // Add Series { // Add a new record rstSeries.AddNew(); rstSeries.m_SeriesInstanceUID = sSeriesInstanceUID; rstSeries.m_StudyInstanceUID = sStudyInstanceUID; rstSeries.m_PatientID = sPatientID; // Modality pElement = pSourceDS->FindFirstElement(NULL, TAG_MODALITY, FALSE); if (pElement) rstSeries.m_Modality = pSourceDS->GetStringValue(pElement, 0, 1); // SeriesNumber pElement = pSourceDS->FindFirstElement(NULL, TAG_SERIES_NUMBER, FALSE); if (pElement) { L_INT32* pnValue = pSourceDS->GetLongValue(pElement, 0, 1); if (pnValue) { rstSeries.m_SeriesNumber = *pnValue; } } rstSeries.Update(); nRet = 0; } rstSeries.Close(); // Does this Image already exist? sQuery = "SELECT * FROM Images where StudyInstanceUID = '" + sStudyInstanceUID + "' AND SeriesInstanceUID = '" + sSeriesInstanceUID + "' AND SOPInstanceUID = '" + sSOPInstanceUID + "';"; CImageRecordset rstImage(&Database); rstImage.Open(CRecordset::dynaset, sQuery); if (rstImage.IsEOF()) // Add Image { // Add a new record rstImage.AddNew(); rstImage.m_SOPInstanceUID = sSOPInstanceUID; rstImage.m_SeriesInstanceUID = sSeriesInstanceUID; rstImage.m_StudyInstanceUID = sStudyInstanceUID; rstImage.m_PatientID = sPatientID; rstImage.m_SOPClassUID = sSOPClassUID; rstImage.m_TransferSyntaxUID = sTransferSyntaxUID; // InstanceNumber pElement = pSourceDS->FindFirstElement(NULL, TAG_INSTANCE_NUMBER, FALSE); if (pElement) { L_INT32* pnValue = pSourceDS->GetLongValue(pElement, 0, 1); if (pnValue) { rstImage.m_InstanceNumber = *pnValue; } } // ReferencedFile rstImage.m_ReferencedFile = szFile; rstImage.Update(); nRet = 0; } rstImage.Close(); } catch(...) { return 1; } Database.Close(); return nRet; } L_BOOL CDICOMSRVDlg::IsValidDate(const pVALUEDATE pDate) const { if (!pDate) return FALSE; if (pDate->nYear < 1753 || pDate->nYear > 9999) return FALSE; if (pDate->nMonth < 1 || pDate->nMonth > 12) return FALSE; if (pDate->nDay < 1 || pDate->nDay > 31) return FALSE; return TRUE; } L_BOOL CDICOMSRVDlg::IsValidTime(const pVALUETIME pTime) const { if (!pTime) return FALSE; if (pTime->nHours > 23) return FALSE; if (pTime->nMinutes > 59) return FALSE; if (pTime->nSeconds > 59) return FALSE; return TRUE; } void CDICOMSRVDlg::OnButtonImport() { L_INT nRet; CString strFileName; TCHAR szFilters[] =_T ("DICOM Files (*.dic)|*.dic|DCM Files (*.dcm)|*.dcm|All files (*.*)|*.*||"); CFileDialog dlg ( TRUE, _T ("dic"), _T ("*.dic"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters); if (dlg.DoModal () != IDOK) { return; } nRet = m_LEADDICOM1.LoadDS((L_CHAR *)((LPCSTR)dlg.GetPathName()), 0); if(nRet != 0) { MessageBox("Error loading DICOM DataSet", "Error", MB_OK); return; } m_bImport = TRUE; L_BOOL bFailed = TRUE; CString sMessage = "Error importing DICOM Data Set"; pDICOMELEMENT pElement = m_LEADDICOM1.FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); if (pElement) { CString sFile = m_LEADDICOM1.GetStringValue(pElement, 0, 1); if (sFile.IsEmpty() == FALSE) { sFile += ".dcm"; nRet = InsertDataSet(&m_LEADDICOM1, sFile); if (nRet == 2) // Already exists? { sMessage = "Data Set already exists in Database!"; } else if (nRet == 0) { CString sFilename = theApp.m_sImagesFolder + sFile; if (m_LEADDICOM1.SaveDS((L_CHAR*)(LPCTSTR) sFilename, DS_METAHEADER_PRESENT | DS_GROUP_LENGTHS) == DICOM_SUCCESS) { // Add the DICOM Data Set (we just saved) to our Directory if (m_SrvDicomDir.InsertDicomDS(m_LEADDICOM1, (L_CHAR*)(LPCTSTR) sFilename) == DICOM_SUCCESS) { bFailed = FALSE; } } } } m_LEADDICOM1.FreeValue(pElement); } if (bFailed) { MessageBox(sMessage, "Error", MB_OK); } m_LEADDICOM1.ResetDS(); // Refresh the DICOM Directory display DisplayDICOMDir(); } void CDICOMSRVDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; HTREEITEM hItem=NULL; pDICOMELEMENT pTemp=NULL; CString szKey; *pResult = 0; hItem = m_DicomDir.GetSelectedItem(); if(!hItem) return; pTemp = (pDICOMELEMENT)m_DicomDir.GetItemData(hItem); if(!pTemp) return; if(pTemp != m_pDisplay) { m_pDisplay = pTemp; m_KeyView.DeleteAllItems(); m_LEAD1.Free(); ::ShowWindow(m_LEAD1hWnd, SW_HIDE); m_KeyView.ShowWindow(SW_SHOW); pTemp = m_SrvDicomDir.GetChildElement(pTemp, TRUE); while(pTemp) { DisplayKey(pTemp, NULL); pTemp = m_SrvDicomDir.GetNextElement(pTemp, TRUE, TRUE); } } } void CDICOMSRVDlg::DisplayKey(pDICOMELEMENT pElement, HTREEITEM hParent) { CString szTag; HTREEITEM hItem=NULL; CString szName; pDICOMELEMENT pTemp=NULL; CString szVal; L_UINT32 lCount; L_UINT32 x; pDICOMTAG pTag=NULL; L_CHAR L_FAR *pVal=NULL; ::ShowWindow(m_LEAD1hWnd, SW_HIDE); m_KeyView.ShowWindow(SW_SHOW); x = 0; szTag.Format("%04X:%04X", GETGROUP(pElement->nTag), GETELEMENT(pElement->nTag)); pTag = LDicomTag::Find(pElement->nTag); szName = "Unknown"; if(pTag) szName = pTag->pszName; //display value(s) szVal = ""; if(pElement->nTag != TAG_PIXEL_DATA) { if(pElement->nLength < 1000) //I don't display anything > 10K { szVal = ": "; lCount = m_SrvDicomDir.GetConvertValue(pElement, NULL); pVal = (L_CHAR L_FAR*)GlobalAllocPtr(GMEM_MOVEABLE, lCount*sizeof(L_CHAR)); if(pVal) { lCount = m_SrvDicomDir.GetConvertValue(pElement, pVal); for(x=0; xFindFirstElement(NULL, TAG_PATIENT_ID, FALSE); if (pElement) { sPatientID = pReqIdentifier->GetStringValue(pElement, 0, 1); } if (sPatientID.IsEmpty()) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, (pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } } // Study Instance UID CString sStudyInstanceUID; if (iQRLevel >= 2) { pElement = pReqIdentifier->FindFirstElement(NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (pElement) { sStudyInstanceUID = pReqIdentifier->GetStringValue(pElement, 0, 1); } if (sStudyInstanceUID.IsEmpty()) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, (pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } } // Series Instance UID CString sSeriesInstanceUID; if (iQRLevel >= 3) { pElement = pReqIdentifier->FindFirstElement(NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (pElement) { sSeriesInstanceUID = pReqIdentifier->GetStringValue(pElement, 0, 1); } if (sSeriesInstanceUID.IsEmpty()) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, (pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } } // SOP Instance UID CString sSOPInstanceUID; if (iQRLevel >= 4) { pElement = pReqIdentifier->FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); if (pElement) { sSOPInstanceUID = pReqIdentifier->GetStringValue(pElement, 0, 1); } if (sSOPInstanceUID.IsEmpty()) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, (pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } } CString sQueryString; // Form the query string sQueryString = "SELECT SOPClassUID,TransferSyntaxUID,ReferencedFile FROM Images WHERE "; if (bPatientRoot) { sQueryString += "PatientID='" + sPatientID + "'"; } if (iQRLevel >= 2) { if (bPatientRoot) sQueryString += " AND "; if (iQRLevel != 2) { sQueryString += "StudyInstanceUID='" + sStudyInstanceUID + "'"; } else { sQueryString += CNetClient::GetQueryStringForUIDs(*pReqIdentifier, TAG_STUDY_INSTANCE_UID, "StudyInstanceUID"); } } if (iQRLevel >= 3) { sQueryString += " AND "; if (iQRLevel != 3) { sQueryString += "SeriesInstanceUID='" + sSeriesInstanceUID + "'"; } else { sQueryString += CNetClient::GetQueryStringForUIDs(*pReqIdentifier, TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID"); } } if (iQRLevel >= 4) { sQueryString += " AND "; sQueryString += CNetClient::GetQueryStringForUIDs(*pReqIdentifier, TAG_SOP_INSTANCE_UID, "SOPInstanceUID"); } // Connect to the database CDatabase Database; try { Database.OpenEx(theApp.m_sConnectionString, CDatabase::noOdbcDialog); } catch(...) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } m_MoveMatches[0].RemoveAll(); m_MoveMatches[1].RemoveAll(); m_MoveMatches[2].RemoveAll(); int iMatchesCount = 0; // Look for matches CImageRecordset ImageRS(&Database); try { ImageRS.Open(CRecordset::dynaset, sQueryString); while (!ImageRS.IsEOF()) { iMatchesCount++; ImageRS.MoveNext(); } if (iMatchesCount) { m_MoveMatches[0].SetSize(iMatchesCount); m_MoveMatches[1].SetSize(iMatchesCount); m_MoveMatches[2].SetSize(iMatchesCount); int iIndex = 0; CDBVariant varValue; ImageRS.MoveFirst(); while (!ImageRS.IsEOF()) { // SOP Class UID ImageRS.GetFieldValue("SOPClassUID", varValue); m_MoveMatches[0][iIndex] = *varValue.m_pstring; // Transfer Syntax UID ImageRS.GetFieldValue("TransferSyntaxUID", varValue); m_MoveMatches[1][iIndex] = *varValue.m_pstring; // Referenced File ImageRS.GetFieldValue("ReferencedFile", varValue); m_MoveMatches[2][iIndex] = *varValue.m_pstring; iIndex++; ImageRS.MoveNext(); } ImageRS.Close(); } else { ImageRS.Close(); m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, COMMAND_STATUS_SUCCESS, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } } catch(...) { m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(sUser, "C-MOVE-RESPONSE sent"); return; } Database.Close(); m_nSuccessfulSubOperations = 0; m_nFailedSubOperations = 0; m_nWarningSubOperations = 0; m_uStoreMessageID = 1; // Connect to the Move Destination AE m_LEADDICOMClient.Connect("", 0, (L_CHAR*)(LPCTSTR) sMoveDstIP, uMoveDstPort); } void CDICOMSRVDlg::OnTimer(UINT nIDEvent) { if (nIDEvent == MOVE_TIMER_ID) { m_nSecondsElapsed++; if (m_nSecondsElapsed > theApp.m_nTimeOut * 60) { KillTimer(MOVE_TIMER_ID); if (m_LEADDICOMClient.IsConnected()) { if (m_LEADDICOMClient.IsAssociated()) { m_LEADDICOMClient.SendReleaseRequest(); } else { m_LEADDICOMClient.Close(); } m_pMoveNet->SendCMoveResponse(m_nMovePresentationID, m_uMoveMessageID, (L_CHAR*)(LPCTSTR) m_sMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); } } } else if (nIDEvent == CLIENTS_TIMER_ID) { HTREEITEM hItem = m_ConnectionList.GetRootItem(); if (!hItem) { KillTimer(CLIENTS_TIMER_ID); } else { CClientData* pClientData; HTREEITEM hTempItem; while (hItem) { pClientData = (CClientData*) m_ConnectionList.GetItemData(hItem); if (pClientData->m_bEnableTimeout) { if (++pClientData->m_uSecondsElapsed > pClientData->m_uTimeout * 60) { pClientData->m_pClient->SendAbort(PDU_ABORT_SOURCE_PROVIDER, PDU_ABORT_REASON_UNKNOWN); pClientData->m_pClient->Close(); LogEvent(pClientData->m_sAETitle, "Timed out - Connection closed"); delete pClientData; hTempItem = hItem; hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); m_ConnectionList.DeleteItem(hTempItem); continue; } } hItem = m_ConnectionList.GetNextItem(hItem, TVGN_NEXT); } } } CDialog::OnTimer(nIDEvent); } void CDICOMSRVDlg::OnServerLogOptions() { CLogOptionsDlg LogOptionsDlg; // Set initial values LogOptionsDlg.m_bGenerateEventsLogFile = theApp.m_bGenerateEventsLogFile; LogOptionsDlg.m_bSaveReceivedCSs = theApp.m_bSaveReceivedCSs; LogOptionsDlg.m_bSaveReceivedDSs = theApp.m_bSaveReceivedDSs; LogOptionsDlg.m_bSaveSentDSs = theApp.m_bSaveSentDSs; LogOptionsDlg.m_sLogFolder = theApp.m_sLogFolder; // Display the dialog box if (LogOptionsDlg.DoModal() != IDOK) return; theApp.m_bGenerateEventsLogFile = LogOptionsDlg.m_bGenerateEventsLogFile; theApp.m_bSaveReceivedCSs = LogOptionsDlg.m_bSaveReceivedCSs; theApp.m_bSaveReceivedDSs = LogOptionsDlg.m_bSaveReceivedDSs; theApp.m_bSaveSentDSs = LogOptionsDlg.m_bSaveSentDSs; theApp.m_sLogFolder = LogOptionsDlg.m_sLogFolder; theApp.PrepareFolder(theApp.m_sLogFolder, "Log"); } void CDICOMSRVDlg::OnCancel() { }