#include "DicSrv.h" #define BIND_COL(hStmt, ColNum, Type, ValuePtr, Length, LenOrInd) \ if (!SQL_SUCCEEDED(SQLBindCol(hStmt, ColNum, Type, ValuePtr, Length, LenOrInd))) \ { \ SQLFreeHandle(SQL_HANDLE_STMT, hStmt); \ return FALSE; \ } BOOL OpenDatabaseConnection(pDBHANDLES pDBHandles) { RETCODE retcode; if (!pDBHandles) return FALSE; // Allocate the environment handle retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &pDBHandles->hEnv); if (SQL_SUCCEEDED(retcode)) { // Set the ODBC version environment attribute retcode = SQLSetEnvAttr(pDBHandles->hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC2, 0); if (SQL_SUCCEEDED(retcode)) { // Allocate the connection handle retcode = SQLAllocHandle(SQL_HANDLE_DBC, pDBHandles->hEnv, &pDBHandles->hDbc); if (SQL_SUCCEEDED(retcode)) { // Establish a connection to the data source retcode = SQLDriverConnect(pDBHandles->hDbc, NULL, gszConnectionString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (SQL_SUCCEEDED(retcode)) { return TRUE; } SQLFreeHandle(SQL_HANDLE_DBC, pDBHandles->hDbc); } } SQLFreeHandle(SQL_HANDLE_ENV, pDBHandles->hEnv); } return FALSE; } VOID CloseDatabaseConnection(pDBHANDLES pDBHandles) { if (!pDBHandles) return; // Close the connection SQLDisconnect(pDBHandles->hDbc); // Free the handles SQLFreeHandle(SQL_HANDLE_DBC, pDBHandles->hDbc); SQLFreeHandle(SQL_HANDLE_ENV, pDBHandles->hEnv); } BOOL OpenPatientsRecordset(SQLHDBC hDbc, pPATIENTSRECORDSET pPatientsRS, LPSTR pszQueryString, BOOL bReadForwardOnly) { SQLRETURN retcode; if (!pPatientsRS || !pszQueryString) return FALSE; // Allocate the statement handle retcode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &pPatientsRS->hStmt); if (!SQL_SUCCEEDED(retcode)) return FALSE; if (!bReadForwardOnly) { retcode = SQLSetStmtAttr(pPatientsRS->hStmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_VALUES, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pPatientsRS->hStmt); return FALSE; } retcode = SQLSetStmtAttr(pPatientsRS->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pPatientsRS->hStmt); return FALSE; } } // Bind columns BIND_COL(pPatientsRS->hStmt, 1, SQL_C_CHAR, pPatientsRS->szPatientID, sizeof(pPatientsRS->szPatientID), &pPatientsRS->lPatientIDLenOrInd) BIND_COL(pPatientsRS->hStmt, 2, SQL_C_CHAR, pPatientsRS->szPatientName, sizeof(pPatientsRS->szPatientName), &pPatientsRS->lPatientNameLenOrInd) BIND_COL(pPatientsRS->hStmt, 3, SQL_C_TIMESTAMP, &pPatientsRS->PatientBirthDate, 0, &pPatientsRS->lPatientBirthDateInd) BIND_COL(pPatientsRS->hStmt, 4, SQL_C_TIMESTAMP, &pPatientsRS->PatientBirthTime, 0, &pPatientsRS->lPatientBirthTimeInd) BIND_COL(pPatientsRS->hStmt, 5, SQL_C_CHAR, pPatientsRS->szPatientSex, sizeof(pPatientsRS->szPatientSex), &pPatientsRS->lPatientSexLenOrInd) BIND_COL(pPatientsRS->hStmt, 6, SQL_C_CHAR, pPatientsRS->szEthnicGroup, sizeof(pPatientsRS->szEthnicGroup), &pPatientsRS->lEthnicGroupLenOrInd) BIND_COL(pPatientsRS->hStmt, 7, SQL_C_CHAR, pPatientsRS->szPatientComments, sizeof(pPatientsRS->szPatientComments), &pPatientsRS->lPatientCommentsLenOrInd) // Execute the statement retcode = SQLExecDirect(pPatientsRS->hStmt, pszQueryString, SQL_NTS); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pPatientsRS->hStmt); return FALSE; } // Fetch the first record retcode = SQLFetchScroll(pPatientsRS->hStmt, SQL_FETCH_NEXT, 0); if (SQL_SUCCEEDED(retcode)) { pPatientsRS->bEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { pPatientsRS->bEOF = TRUE; return TRUE; } else { SQLFreeHandle(SQL_HANDLE_STMT, pPatientsRS->hStmt); return FALSE; } } BOOL OpenStudiesRecordset(SQLHDBC hDbc, pSTUDIESRECORDSET pStudiesRS, LPSTR pszQueryString, BOOL bReadForwardOnly) { SQLRETURN retcode; if (!pStudiesRS || !pszQueryString) return FALSE; // Allocate the statement handle retcode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &pStudiesRS->hStmt); if (!SQL_SUCCEEDED(retcode)) return FALSE; if (!bReadForwardOnly) { retcode = SQLSetStmtAttr(pStudiesRS->hStmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_VALUES, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pStudiesRS->hStmt); return FALSE; } retcode = SQLSetStmtAttr(pStudiesRS->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pStudiesRS->hStmt); return FALSE; } } // Bind columns BIND_COL(pStudiesRS->hStmt, 1, SQL_C_CHAR, pStudiesRS->szStudyInstanceUID, sizeof(pStudiesRS->szStudyInstanceUID), &pStudiesRS->lStudyInstanceUIDLenOrInd) BIND_COL(pStudiesRS->hStmt, 2, SQL_C_TIMESTAMP, &pStudiesRS->StudyDate, 0, &pStudiesRS->lStudyDateInd) BIND_COL(pStudiesRS->hStmt, 3, SQL_C_TIMESTAMP, &pStudiesRS->StudyTime, 0, &pStudiesRS->lStudyTimeInd) BIND_COL(pStudiesRS->hStmt, 4, SQL_C_CHAR, pStudiesRS->szAccessionNumber, sizeof(pStudiesRS->szAccessionNumber), &pStudiesRS->lAccessionNumberLenOrInd) BIND_COL(pStudiesRS->hStmt, 5, SQL_C_CHAR, pStudiesRS->szStudyID, sizeof(pStudiesRS->szStudyID), &pStudiesRS->lStudyIDLenOrInd) BIND_COL(pStudiesRS->hStmt, 6, SQL_C_CHAR, pStudiesRS->szPatientName, sizeof(pStudiesRS->szPatientName), &pStudiesRS->lPatientNameLenOrInd) BIND_COL(pStudiesRS->hStmt, 7, SQL_C_CHAR, pStudiesRS->szPatientID, sizeof(pStudiesRS->szPatientID), &pStudiesRS->lPatientIDLenOrInd) BIND_COL(pStudiesRS->hStmt, 8, SQL_C_CHAR, pStudiesRS->szStudyDescription, sizeof(pStudiesRS->szStudyDescription), &pStudiesRS->lStudyDescriptionLenOrInd) // Execute the statement retcode = SQLExecDirect(pStudiesRS->hStmt, pszQueryString, SQL_NTS); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pStudiesRS->hStmt); return FALSE; } // Fetch the first record retcode = SQLFetchScroll(pStudiesRS->hStmt, SQL_FETCH_NEXT, 0); if (SQL_SUCCEEDED(retcode)) { pStudiesRS->bEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { pStudiesRS->bEOF = TRUE; return TRUE; } else { SQLFreeHandle(SQL_HANDLE_STMT, pStudiesRS->hStmt); return FALSE; } } BOOL OpenSeriesRecordset(SQLHDBC hDbc, pSERIESRECORDSET pSeriesRS, LPSTR pszQueryString, BOOL bReadForwardOnly) { SQLRETURN retcode; if (!pSeriesRS || !pszQueryString) return FALSE; // Allocate the statement handle retcode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &pSeriesRS->hStmt); if (!SQL_SUCCEEDED(retcode)) return FALSE; if (!bReadForwardOnly) { retcode = SQLSetStmtAttr(pSeriesRS->hStmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_VALUES, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pSeriesRS->hStmt); return FALSE; } retcode = SQLSetStmtAttr(pSeriesRS->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pSeriesRS->hStmt); return FALSE; } } // Bind columns BIND_COL(pSeriesRS->hStmt, 1, SQL_C_CHAR, pSeriesRS->szSeriesInstanceUID, sizeof(pSeriesRS->szSeriesInstanceUID), &pSeriesRS->lSeriesInstanceUIDLenOrInd) BIND_COL(pSeriesRS->hStmt, 2, SQL_C_CHAR, pSeriesRS->szStudyInstanceUID, sizeof(pSeriesRS->szStudyInstanceUID), &pSeriesRS->lStudyInstanceUIDLenOrInd) BIND_COL(pSeriesRS->hStmt, 3, SQL_C_CHAR, pSeriesRS->szModality, sizeof(pSeriesRS->szModality), &pSeriesRS->lModalityLenOrInd) BIND_COL(pSeriesRS->hStmt, 4, SQL_C_SLONG, &pSeriesRS->lSeriesNumber, 0, &pSeriesRS->lSeriesNumberInd) BIND_COL(pSeriesRS->hStmt, 5, SQL_C_CHAR, pSeriesRS->szPatientID, sizeof(pSeriesRS->szPatientID), &pSeriesRS->lPatientIDLenOrInd) // Execute the statement retcode = SQLExecDirect(pSeriesRS->hStmt, pszQueryString, SQL_NTS); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pSeriesRS->hStmt); return FALSE; } // Fetch the first record retcode = SQLFetchScroll(pSeriesRS->hStmt, SQL_FETCH_NEXT, 0); if (SQL_SUCCEEDED(retcode)) { pSeriesRS->bEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { pSeriesRS->bEOF = TRUE; return TRUE; } else { SQLFreeHandle(SQL_HANDLE_STMT, pSeriesRS->hStmt); return FALSE; } } BOOL OpenImagesRecordset(SQLHDBC hDbc, pIMAGESRECORDSET pImagesRS, LPSTR pszQueryString, BOOL bReadForwardOnly) { SQLRETURN retcode; if (!pImagesRS || !pszQueryString) return FALSE; // Allocate the statement handle retcode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &pImagesRS->hStmt); if (!SQL_SUCCEEDED(retcode)) return FALSE; if (!bReadForwardOnly) { retcode = SQLSetStmtAttr(pImagesRS->hStmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_VALUES, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pImagesRS->hStmt); return FALSE; } retcode = SQLSetStmtAttr(pImagesRS->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pImagesRS->hStmt); return FALSE; } } // Bind columns BIND_COL(pImagesRS->hStmt, 1, SQL_C_CHAR, pImagesRS->szSOPInstanceUID, sizeof(pImagesRS->szSOPInstanceUID), &pImagesRS->lSOPInstanceUIDLenOrInd) BIND_COL(pImagesRS->hStmt, 2, SQL_C_CHAR, pImagesRS->szSeriesInstanceUID, sizeof(pImagesRS->szSeriesInstanceUID), &pImagesRS->lSeriesInstanceUIDLenOrInd) BIND_COL(pImagesRS->hStmt, 3, SQL_C_CHAR, pImagesRS->szStudyInstanceUID, sizeof(pImagesRS->szStudyInstanceUID), &pImagesRS->lStudyInstanceUIDLenOrInd) BIND_COL(pImagesRS->hStmt, 4, SQL_C_SLONG, &pImagesRS->lInstanceNumber, 0, &pImagesRS->lInstanceNumberInd) BIND_COL(pImagesRS->hStmt, 5, SQL_C_CHAR, pImagesRS->szReferencedFile, sizeof(pImagesRS->szReferencedFile), &pImagesRS->lReferencedFileLenOrInd) BIND_COL(pImagesRS->hStmt, 6, SQL_C_CHAR, pImagesRS->szPatientID, sizeof(pImagesRS->szPatientID), &pImagesRS->lPatientIDLenOrInd) BIND_COL(pImagesRS->hStmt, 7, SQL_C_CHAR, pImagesRS->szSOPClassUID, sizeof(pImagesRS->szSOPClassUID), &pImagesRS->lSOPClassUIDLenOrInd) BIND_COL(pImagesRS->hStmt, 8, SQL_C_CHAR, pImagesRS->szTransferSyntaxUID, sizeof(pImagesRS->szTransferSyntaxUID), &pImagesRS->lTransferSyntaxUIDLenOrInd) // Execute the statement retcode = SQLExecDirect(pImagesRS->hStmt, pszQueryString, SQL_NTS); if (!SQL_SUCCEEDED(retcode)) { SQLFreeHandle(SQL_HANDLE_STMT, pImagesRS->hStmt); return FALSE; } // Fetch the first record retcode = SQLFetchScroll(pImagesRS->hStmt, SQL_FETCH_NEXT, 0); if (SQL_SUCCEEDED(retcode)) { pImagesRS->bEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { pImagesRS->bEOF = TRUE; return TRUE; } else { SQLFreeHandle(SQL_HANDLE_STMT, pImagesRS->hStmt); return FALSE; } } VOID CloseRecordset(PVOID pRecordset) { SQLHSTMT hStmt; if (!pRecordset) return; hStmt = (SQLHSTMT) *(((BOOL*) pRecordset) + 1); // Close the cursor and then free the handle SQLCloseCursor(hStmt); SQLFreeHandle(SQL_HANDLE_STMT, hStmt); } BOOL GetNextRecord(PVOID pRecordset) { RETCODE retcode; BOOL* pbEOF; SQLHSTMT hStmt; if (!pRecordset) return FALSE; pbEOF = (BOOL*) pRecordset; hStmt = (SQLHSTMT) *(pbEOF + 1); // Fetch the next record retcode = SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 0); if (SQL_SUCCEEDED(retcode)) { *pbEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { *pbEOF = TRUE; return TRUE; } else { return FALSE; } } BOOL GetFirstRecord(PVOID pRecordset) { RETCODE retcode; BOOL* pbEOF; SQLHSTMT hStmt; if (!pRecordset) return FALSE; pbEOF = (BOOL*) pRecordset; hStmt = (SQLHSTMT) *(pbEOF + 1); // Move to the first record retcode = SQLFetchScroll(hStmt, SQL_FETCH_FIRST, 0); if (SQL_SUCCEEDED(retcode)) { *pbEOF = FALSE; return TRUE; } else if (retcode == SQL_NO_DATA) { *pbEOF = TRUE; return TRUE; } else { return FALSE; } } BOOL AddNewRecord(PVOID pRecordset) { SQLHSTMT hStmt; if (!pRecordset) return FALSE; hStmt = (SQLHSTMT) *(((BOOL*) pRecordset) + 1); // Add the new record if (SQL_SUCCEEDED(SQLSetPos(hStmt, 1, SQL_ADD, SQL_LOCK_NO_CHANGE))) return TRUE; return FALSE; } BOOL DeleteRecord(PVOID pRecordset) { SQLHSTMT hStmt; if (!pRecordset) return FALSE; hStmt = (SQLHSTMT) *(((BOOL*) pRecordset) + 1); // Delete the record if (SQL_SUCCEEDED(SQLSetPos(hStmt, 1, SQL_DELETE, SQL_LOCK_NO_CHANGE))) return TRUE; return FALSE; } VOID WrapUpDatabase(pDBHANDLES pDBHandles, PVOID pRS1, PVOID pRS2, PVOID pRS3, PVOID pRS4) { CloseRecordset(pRS1); CloseRecordset(pRS2); CloseRecordset(pRS3); CloseRecordset(pRS4); CloseDatabaseConnection(pDBHandles); } BOOL DeletePatient(HWND hDlg, L_CHAR* pszPatientID) { DBHANDLES db; PATIENTSRECORDSET PatientsRS; STUDIESRECORDSET StudiesRS; char szQueryString[512]; if (!pszPatientID) return FALSE; if (!OpenDatabaseConnection(&db)) { MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } // Find all Studies related to this Patient and delete them wsprintf(szQueryString, "SELECT * FROM Studies WHERE PatientID = '%s'", pszPatientID); if (!OpenStudiesRecordset(db.hDbc, &StudiesRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } while (!StudiesRS.bEOF) { if (!DeleteStudy(hDlg, &db, &StudiesRS, StudiesRS.szStudyInstanceUID)) { WrapUpDatabase(&db, &StudiesRS, NULL, NULL, NULL); return FALSE; } if (!GetNextRecord(&StudiesRS)) { WrapUpDatabase(&db, &StudiesRS, NULL, NULL, NULL); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } } CloseRecordset(&StudiesRS); // Now find this Patient and delete its record wsprintf(szQueryString, "SELECT * FROM Patients WHERE PatientID = '%s'", pszPatientID); if (!OpenPatientsRecordset(db.hDbc, &PatientsRS, szQueryString, FALSE)) { WrapUpDatabase(&db, NULL, NULL, NULL, NULL); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } if (!PatientsRS.bEOF) { DeleteRecord(&PatientsRS); } CloseRecordset(&PatientsRS); CloseDatabaseConnection(&db); return TRUE; } BOOL DeleteStudy(HWND hDlg, pDBHANDLES pDb, pSTUDIESRECORDSET pStudiesRS, L_CHAR* pszStudyInstanceUID) { DBHANDLES db; STUDIESRECORDSET StudiesRS; SERIESRECORDSET SeriesRS; char szQueryString[512]; if (!pszStudyInstanceUID) return FALSE; if (pDb) { db = *pDb; } else if (!OpenDatabaseConnection(&db)) { MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } // Find all Series related to this Study and delete them wsprintf(szQueryString, "SELECT * FROM Series WHERE StudyInstanceUID = '%s'", pszStudyInstanceUID); if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, FALSE)) { if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } while (!SeriesRS.bEOF) { if (!DeleteSeries(hDlg, &db, &SeriesRS, pszStudyInstanceUID, SeriesRS.szSeriesInstanceUID)) { CloseRecordset(&SeriesRS); if (!pDb) CloseDatabaseConnection(&db); return FALSE; } if (!GetNextRecord(&SeriesRS)) { CloseRecordset(&SeriesRS); if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } } CloseRecordset(&SeriesRS); // Now delete the record of this Study if (pDb && pStudiesRS) { DeleteRecord(pStudiesRS); } else // We have to find it first { wsprintf(szQueryString, "SELECT * FROM Studies WHERE StudyInstanceUID = '%s'", pszStudyInstanceUID); if (!OpenStudiesRecordset(db.hDbc, &StudiesRS, szQueryString, FALSE)) { if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } if (!StudiesRS.bEOF) { DeleteRecord(&StudiesRS); } CloseRecordset(&StudiesRS); } if (!pDb) CloseDatabaseConnection(&db); return TRUE; } BOOL DeleteSeries(HWND hDlg, pDBHANDLES pDb, pSERIESRECORDSET pSeriesRS, L_CHAR* pszStudyInstanceUID, L_CHAR* pszSeriesInstanceUID) { DBHANDLES db; SERIESRECORDSET SeriesRS; IMAGESRECORDSET ImagesRS; char szQueryString[1024]; if (!pszStudyInstanceUID || !pszSeriesInstanceUID) return FALSE; if (pDb) { db = *pDb; } else if (!OpenDatabaseConnection(&db)) { MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } // Find all Images related to this Series and delete them wsprintf(szQueryString, "SELECT * FROM Images WHERE StudyInstanceUID = '%s' AND SeriesInstanceUID = '%s'", pszStudyInstanceUID, pszSeriesInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, FALSE)) { if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } while (!ImagesRS.bEOF) { if (!DeleteImage(hDlg, &db, &ImagesRS, pszStudyInstanceUID, pszSeriesInstanceUID, ImagesRS.szSOPInstanceUID)) { CloseRecordset(&ImagesRS); if (!pDb) CloseDatabaseConnection(&db); return FALSE; } if (!GetNextRecord(&ImagesRS)) { CloseRecordset(&ImagesRS); if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } } CloseRecordset(&ImagesRS); // Now delete the record of this Series if (pDb && pSeriesRS) { DeleteRecord(pSeriesRS); } else // We have to find it first { wsprintf(szQueryString, "SELECT * FROM Series WHERE StudyInstanceUID = '%s' AND SeriesInstanceUID = '%s'", pszStudyInstanceUID, pszSeriesInstanceUID); if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, FALSE)) { if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } if (!SeriesRS.bEOF) { DeleteRecord(&SeriesRS); } CloseRecordset(&SeriesRS); } if (!pDb) CloseDatabaseConnection(&db); return TRUE; } BOOL DeleteImage(HWND hDlg, pDBHANDLES pDb, pIMAGESRECORDSET pImagesRS, L_CHAR* pszStudyInstanceUID, L_CHAR* pszSeriesInstanceUID, L_CHAR* pszSOPInstanceUID) { DBHANDLES db; IMAGESRECORDSET ImagesRS; char szBuffer[1024]; if (!pszStudyInstanceUID || !pszSeriesInstanceUID || !pszSOPInstanceUID) return FALSE; if (pDb) { db = *pDb; } else if (!OpenDatabaseConnection(&db)) { MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } // Delete the record of this Image if (pDb && pImagesRS) { // The DICOM file of this Image wsprintf(szBuffer, "%s%s", gszImagesFolder, pImagesRS->szReferencedFile); DeleteRecord(pImagesRS); } else // We have to find it first { wsprintf(szBuffer, "SELECT * FROM Images WHERE StudyInstanceUID = '%s' AND SeriesInstanceUID = '%s' AND SOPInstanceUID = '%s'", pszStudyInstanceUID, pszSeriesInstanceUID, pszSOPInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szBuffer, FALSE)) { if (!pDb) CloseDatabaseConnection(&db); MessageBox(hDlg, "Database error.", "Error", MB_OK | MB_ICONERROR); return FALSE; } if (!ImagesRS.bEOF) { // The DICOM file of this Image wsprintf(szBuffer, "%s%s", gszImagesFolder, ImagesRS.szReferencedFile); DeleteRecord(&ImagesRS); } CloseRecordset(&ImagesRS); } // Delete the DICOM file of this Image DeleteFile(szBuffer); if (!pDb) CloseDatabaseConnection(&db); return TRUE; } BOOL IsValidDate(const pVALUEDATE pDate) { 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; } BOOL IsValidTime(const pVALUETIME pTime) { if (!pTime) return FALSE; if (pTime->nHours > 23) return FALSE; if (pTime->nMinutes > 59) return FALSE; if (pTime->nSeconds > 59) return FALSE; return TRUE; } // Possible return values: (0: Success), (1: Failure), (2: Already exists) int InsertDataSet(HWND hDlg, HDICOMDS hSourceDS, L_CHAR* pszFile) { DBHANDLES db; PATIENTSRECORDSET PatientsRS; STUDIESRECORDSET StudiesRS; SERIESRECORDSET SeriesRS; IMAGESRECORDSET ImagesRS; char szQueryString[1024]; pDICOMELEMENT pElement; L_CHAR* pszPatientID; L_CHAR* pszPatientName; L_CHAR* pszStudyInstanceUID; L_CHAR* pszSeriesInstanceUID; L_CHAR* pszSOPInstanceUID; L_CHAR* pszSOPClassUID; L_CHAR* pszTransferSyntaxUID; L_CHAR* pszValue; pVALUEDATE pDate; pVALUETIME pTime; int iRet; L_INT32* pnValue; // Patient ID pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_ID, FALSE); if(!pElement) return 1; pszPatientID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); if (!lstrlen(pszPatientID)) return 1; // Patient Name pszPatientName = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_NAME, FALSE); if (pElement) pszPatientName = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); // Study Instance UID pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (!pElement) return 1; pszStudyInstanceUID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); if (!lstrlen(pszStudyInstanceUID)) return 1; // Series Instance UID pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (!pElement) return 1; pszSeriesInstanceUID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); if (!lstrlen(pszSeriesInstanceUID)) return 1; // SOP Instance UID pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_SOP_INSTANCE_UID, FALSE); if (!pElement) return 1; pszSOPInstanceUID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); if (!lstrlen(pszSOPInstanceUID)) return 1; // SOP Class UID pszSOPClassUID = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_SOP_CLASS_UID, FALSE); if (!pElement) { pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_MEDIA_STORAGE_SOP_CLASS_UID, FALSE); } if (pElement) { pszSOPClassUID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (!lstrlen(pszSOPClassUID)) { pszSOPClassUID = "1.1.1.1"; } // Transfer Syntax UID pszTransferSyntaxUID = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_TRANSFER_SYNTAX_UID, FALSE); if (pElement) { pszTransferSyntaxUID = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (!lstrlen(pszTransferSyntaxUID)) { pszTransferSyntaxUID = UID_IMPLICIT_VR_LITTLE_ENDIAN; } if (!OpenDatabaseConnection(&db)) { return 1; } iRet = 2; // Does this Patient already exist? wsprintf(szQueryString, "SELECT * FROM Patients WHERE PatientID = '%s'", pszPatientID); if (!OpenPatientsRecordset(db.hDbc, &PatientsRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); return 1; } if (PatientsRS.bEOF) // Add Patient { // Set the record data of the new Patient // PatientID lstrcpy(PatientsRS.szPatientID, pszPatientID); PatientsRS.lPatientIDLenOrInd = SQL_NTS; // PatientName if (lstrlen(pszPatientName)) { lstrcpy(PatientsRS.szPatientName, pszPatientName); PatientsRS.lPatientNameLenOrInd = SQL_NTS; } else { PatientsRS.lPatientNameLenOrInd = SQL_NULL_DATA; } // PatientBirthDate PatientsRS.lPatientBirthDateInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_BIRTH_DATE, FALSE); if (pElement) { pDate = L_DicomGetDateValue(hSourceDS, pElement, 0, 1); if (IsValidDate(pDate)) { memset(&PatientsRS.PatientBirthDate, 0, sizeof(TIMESTAMP_STRUCT)); PatientsRS.PatientBirthDate.year = pDate->nYear; PatientsRS.PatientBirthDate.month = pDate->nMonth; PatientsRS.PatientBirthDate.day = pDate->nDay; PatientsRS.lPatientBirthDateInd = sizeof(TIMESTAMP_STRUCT); } } // PatientBirthTime PatientsRS.lPatientBirthTimeInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_BIRTH_TIME, FALSE); if (pElement) { pTime = L_DicomGetTimeValue(hSourceDS, pElement, 0, 1); if (IsValidTime(pTime)) { memset(&PatientsRS.PatientBirthTime, 0, sizeof(TIMESTAMP_STRUCT)); PatientsRS.PatientBirthTime.year = 9999; PatientsRS.PatientBirthTime.month = 1; PatientsRS.PatientBirthTime.day = 1; PatientsRS.PatientBirthTime.hour = pTime->nHours; PatientsRS.PatientBirthTime.minute = pTime->nMinutes; PatientsRS.PatientBirthTime.second = pTime->nSeconds; PatientsRS.lPatientBirthTimeInd = sizeof(TIMESTAMP_STRUCT); } } // PatientSex pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_SEX, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(PatientsRS.szPatientSex, pszValue); PatientsRS.lPatientSexLenOrInd = SQL_NTS; } else { PatientsRS.lPatientSexLenOrInd = SQL_NULL_DATA; } // EthnicGroup pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_ETHNIC_GROUP, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(PatientsRS.szEthnicGroup, pszValue); PatientsRS.lEthnicGroupLenOrInd = SQL_NTS; } else { PatientsRS.lEthnicGroupLenOrInd = SQL_NULL_DATA; } // PatientComments pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_PATIENT_COMMENTS, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(PatientsRS.szPatientComments, pszValue); PatientsRS.lPatientCommentsLenOrInd = SQL_NTS; } else { PatientsRS.lPatientCommentsLenOrInd = SQL_NULL_DATA; } if (!AddNewRecord(&PatientsRS)) { WrapUpDatabase(&db, &PatientsRS, NULL, NULL, NULL); return 1; } iRet = 0; } CloseRecordset(&PatientsRS); // Does this Study already exist? wsprintf(szQueryString, "SELECT * FROM Studies WHERE PatientID = '%s' AND StudyInstanceUID = '%s'", pszPatientID, pszStudyInstanceUID); if (!OpenStudiesRecordset(db.hDbc, &StudiesRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); return 1; } if (StudiesRS.bEOF) // Add Study { // Set the record data of the new Study // StudyInstanceUID lstrcpy(StudiesRS.szStudyInstanceUID, pszStudyInstanceUID); StudiesRS.lStudyInstanceUIDLenOrInd = SQL_NTS; // StudyDate StudiesRS.lStudyDateInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_STUDY_DATE, FALSE); if (pElement) { pDate = L_DicomGetDateValue(hSourceDS, pElement, 0, 1); if (IsValidDate(pDate)) { memset(&StudiesRS.StudyDate, 0, sizeof(TIMESTAMP_STRUCT)); StudiesRS.StudyDate.year = pDate->nYear; StudiesRS.StudyDate.month = pDate->nMonth; StudiesRS.StudyDate.day = pDate->nDay; StudiesRS.lStudyDateInd = sizeof(TIMESTAMP_STRUCT); } } // StudyTime StudiesRS.lStudyTimeInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_STUDY_TIME, FALSE); if (pElement) { pTime = L_DicomGetTimeValue(hSourceDS, pElement, 0, 1); if (IsValidTime(pTime)) { memset(&StudiesRS.StudyTime, 0, sizeof(TIMESTAMP_STRUCT)); StudiesRS.StudyTime.year = 9999; StudiesRS.StudyTime.month = 1; StudiesRS.StudyTime.day = 1; StudiesRS.StudyTime.hour = pTime->nHours; StudiesRS.StudyTime.minute = pTime->nMinutes; StudiesRS.StudyTime.second = pTime->nSeconds; StudiesRS.lStudyTimeInd = sizeof(TIMESTAMP_STRUCT); } } // AccessionNumber pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_ACCESSION_NUMBER, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(StudiesRS.szAccessionNumber, pszValue); StudiesRS.lAccessionNumberLenOrInd = SQL_NTS; } else { StudiesRS.lAccessionNumberLenOrInd = SQL_NULL_DATA; } // StudyID pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_STUDY_ID, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(StudiesRS.szStudyID, pszValue); StudiesRS.lStudyIDLenOrInd = SQL_NTS; } else { StudiesRS.lStudyIDLenOrInd = SQL_NULL_DATA; } // PatientName if (lstrlen(pszPatientName)) { lstrcpy(StudiesRS.szPatientName, pszPatientName); StudiesRS.lPatientNameLenOrInd = SQL_NTS; } else { StudiesRS.lPatientNameLenOrInd = SQL_NULL_DATA; } // PatientID lstrcpy(StudiesRS.szPatientID, pszPatientID); StudiesRS.lPatientIDLenOrInd = SQL_NTS; // StudyDescription pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_STUDY_DESCRIPTION, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(StudiesRS.szStudyDescription, pszValue); StudiesRS.lStudyDescriptionLenOrInd = SQL_NTS; } else { StudiesRS.lStudyDescriptionLenOrInd = SQL_NULL_DATA; } if (!AddNewRecord(&StudiesRS)) { WrapUpDatabase(&db, &StudiesRS, NULL, NULL, NULL); return 1; } iRet = 0; } CloseRecordset(&StudiesRS); // Does this Series already exist? wsprintf(szQueryString, "SELECT * FROM Series where StudyInstanceUID = '%s' AND SeriesInstanceUID = '%s'", pszStudyInstanceUID, pszSeriesInstanceUID); if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); return 1; } if (SeriesRS.bEOF) // Add Series { // Set the record data of the new Series // SeriesInstanceUID lstrcpy(SeriesRS.szSeriesInstanceUID, pszSeriesInstanceUID); SeriesRS.lSeriesInstanceUIDLenOrInd = SQL_NTS; // StudyInstanceUID lstrcpy(SeriesRS.szStudyInstanceUID, pszStudyInstanceUID); SeriesRS.lStudyInstanceUIDLenOrInd = SQL_NTS; // Modality pszValue = NULL; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_MODALITY, FALSE); if (pElement) { pszValue = L_DicomGetStringValue(hSourceDS, pElement, 0, 1); } if (lstrlen(pszValue)) { lstrcpy(SeriesRS.szModality, pszValue); SeriesRS.lModalityLenOrInd = SQL_NTS; } else { SeriesRS.lModalityLenOrInd = SQL_NULL_DATA; } // SeriesNumber SeriesRS.lSeriesNumberInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_SERIES_NUMBER, FALSE); if (pElement) { pnValue = L_DicomGetLongValue(hSourceDS, pElement, 0, 1); if (pnValue) { SeriesRS.lSeriesNumber = *pnValue; SeriesRS.lSeriesNumberInd = sizeof(long); } } // PatientID lstrcpy(SeriesRS.szPatientID, pszPatientID); SeriesRS.lPatientIDLenOrInd = SQL_NTS; if (!AddNewRecord(&SeriesRS)) { CloseRecordset(&SeriesRS); CloseDatabaseConnection(&db); return 1; } iRet = 0; } CloseRecordset(&SeriesRS); // Does this Image already exist? wsprintf(szQueryString, "SELECT * FROM Images where StudyInstanceUID = '%s' AND SeriesInstanceUID = '%s' AND SOPInstanceUID = '%s'", pszStudyInstanceUID, pszSeriesInstanceUID, pszSOPInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); return 1; } if (ImagesRS.bEOF) // Add Image { // Set the record data of the new Image // SOPInstanceUID lstrcpy(ImagesRS.szSOPInstanceUID, pszSOPInstanceUID); ImagesRS.lSOPInstanceUIDLenOrInd = SQL_NTS; // SeriesInstanceUID lstrcpy(ImagesRS.szSeriesInstanceUID, pszSeriesInstanceUID); ImagesRS.lSeriesInstanceUIDLenOrInd = SQL_NTS; // StudyInstanceUID lstrcpy(ImagesRS.szStudyInstanceUID, pszStudyInstanceUID); ImagesRS.lStudyInstanceUIDLenOrInd = SQL_NTS; // InstanceNumber ImagesRS.lInstanceNumberInd = SQL_NULL_DATA; pElement = L_DicomFindFirstElement(hSourceDS, NULL, TAG_INSTANCE_NUMBER, FALSE); if (pElement) { pnValue = L_DicomGetLongValue(hSourceDS, pElement, 0, 1); if (pnValue) { ImagesRS.lInstanceNumber = *pnValue; ImagesRS.lInstanceNumberInd = sizeof(long); } } // ReferencedFile if (lstrlen(pszFile)) { lstrcpy(ImagesRS.szReferencedFile, pszFile); ImagesRS.lReferencedFileLenOrInd = SQL_NTS; } else { ImagesRS.lReferencedFileLenOrInd = SQL_NULL_DATA; } // PatientID lstrcpy(ImagesRS.szPatientID, pszPatientID); ImagesRS.lPatientIDLenOrInd = SQL_NTS; // SOPClassUID lstrcpy(ImagesRS.szSOPClassUID, pszSOPClassUID); ImagesRS.lSOPClassUIDLenOrInd = SQL_NTS; // TransferSyntaxUID lstrcpy(ImagesRS.szTransferSyntaxUID, pszTransferSyntaxUID); ImagesRS.lTransferSyntaxUIDLenOrInd = SQL_NTS; if (!AddNewRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); return 1; } iRet = 0; } CloseRecordset(&ImagesRS); CloseDatabaseConnection(&db); return iRet; } // For the Wild Card Matching: Replaces every '*' with '%' and every '?' with '_'. LPSTR PrepareForWCM(LPCSTR pszValue, LPSTR pszPreparedValue) { int iLength, i; if (!pszPreparedValue) return NULL; lstrcpy(pszPreparedValue, pszValue ? pszValue : ""); iLength = lstrlen(pszPreparedValue); for (i = 0; i < iLength; i++) { if (pszPreparedValue[i] == '*') { pszPreparedValue[i] = '%'; } else if (pszPreparedValue[i] == '?') { pszPreparedValue[i] = '_'; } } return pszPreparedValue; } VOID InsertKeyElement(HDICOMDS hRspIdentifier, HDICOMDS hReqIdentifier, L_UINT32 uTag, L_UINT16 uVR) { pDICOMELEMENT pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, uTag, FALSE); if (pElement) { L_DicomInsertElement(hRspIdentifier, NULL, FALSE, uTag, uVR, FALSE, 0); } } // iQRLevel: (1: Ptn), (2: Std), (3: Srs), (4: Img) VOID PrepareRspIdentifier(HDICOMDS hRspIdentifier, HDICOMDS hReqIdentifier, int iQRLevel, BOOL bPatientRoot) { if (!hRspIdentifier || !hReqIdentifier) return; L_DicomInitDS(hRspIdentifier, CLASS_UNKNOWN, DS_METAHEADER_ABSENT | DS_LITTLE_ENDIAN | DS_EXPLICIT_VR); // The Query/Retrieve Level switch (iQRLevel) { case 1: SetElement(hRspIdentifier, NULL, TAG_QUERY_RETRIEVE_LEVEL, VR_CS, "PATIENT"); break; case 2: SetElement(hRspIdentifier, NULL, TAG_QUERY_RETRIEVE_LEVEL, VR_CS, "STUDY"); break; case 3: SetElement(hRspIdentifier, NULL, TAG_QUERY_RETRIEVE_LEVEL, VR_CS, "SERIES"); break; case 4: SetElement(hRspIdentifier, NULL, TAG_QUERY_RETRIEVE_LEVEL, VR_CS, "IMAGE"); break; } // The Unique Keys if (bPatientRoot) { L_DicomInsertElement(hRspIdentifier, NULL, FALSE, TAG_PATIENT_ID, VR_LO, FALSE, 0); } if (iQRLevel >= 2) { L_DicomInsertElement(hRspIdentifier, NULL, FALSE, TAG_STUDY_INSTANCE_UID, VR_UI, FALSE, 0); } if (iQRLevel >= 3) { L_DicomInsertElement(hRspIdentifier, NULL, FALSE, TAG_SERIES_INSTANCE_UID, VR_UI, FALSE, 0); } if (iQRLevel >= 4) { L_DicomInsertElement(hRspIdentifier, NULL, FALSE, TAG_SOP_INSTANCE_UID, VR_UI, FALSE, 0); } // The Required and Optional Keys // (Note: This demo supports only the existence of some Optional Keys) switch (iQRLevel) { case 1: // Required Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_NAME, VR_PN); // Optional Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_BIRTH_DATE, VR_DA); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_BIRTH_TIME, VR_TM); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_SEX, VR_CS); //InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_OTHER_PATIENT_IDS, VR_LO); //InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_OTHER_PATIENT_NAMES, VR_PN); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_ETHNIC_GROUP, VR_SH); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_COMMENTS, VR_LT); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_PATIENT_RELATED_STUDIES, VR_IS); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_PATIENT_RELATED_SERIES, VR_IS); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES, VR_IS); break; case 2: // Required Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_STUDY_DATE, VR_DA); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_STUDY_TIME, VR_TM); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_ACCESSION_NUMBER, VR_SH); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_STUDY_ID, VR_SH); if (!bPatientRoot) { InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_NAME, VR_PN); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_PATIENT_ID, VR_LO); } // Optional Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_STUDY_DESCRIPTION, VR_LO); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_STUDY_RELATED_SERIES, VR_IS); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_STUDY_RELATED_INSTANCES, VR_IS); break; case 3: // Required Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_MODALITY, VR_CS); InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_SERIES_NUMBER, VR_IS); // Optional Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_NUMBER_OF_SERIES_RELATED_INSTANCES, VR_IS); break; case 4: // Required Keys: InsertKeyElement(hRspIdentifier, hReqIdentifier, TAG_INSTANCE_NUMBER, VR_IS); break; } } VOID SetKeyElement(HDICOMDS hRspIdentifier, LPSTR pszValue, L_UINT32 uTag) { pDICOMELEMENT pElement = L_DicomFindFirstElement(hRspIdentifier, NULL, uTag, FALSE); if (pElement) { L_DicomSetConvertValue(hRspIdentifier, pElement, pszValue, 1); } } VOID SetTimeDateKeyElement(HDICOMDS hRspIdentifier, TIMESTAMP_STRUCT* pTS, L_UINT32 uTag, L_BOOL bTimeValue) { pDICOMELEMENT pElement; VALUEDATE vd; VALUETIME vt; if (!pTS) return; pElement = L_DicomFindFirstElement(hRspIdentifier, NULL, uTag, FALSE); if (pElement) { if (bTimeValue) { vt.nHours = pTS->hour; vt.nMinutes = pTS->minute; vt.nSeconds = pTS->second; vt.nFractions = pTS->fraction; L_DicomSetTimeValue(hRspIdentifier, pElement, &vt, 1); } else { vd.nYear = pTS->year; vd.nMonth = pTS->month; vd.nDay = pTS->day; L_DicomSetDateValue(hRspIdentifier, pElement, &vd, 1); } } } // For the List of UID Matching LPSTR GetQueryStringForUIDs(HDICOMDS hReqIdentifier, L_UINT32 uTag, LPCSTR pszFieldName, LPSTR pszQueryString) { pDICOMELEMENT pElement; L_CHAR* pszUID; L_UINT32 uUIDsCount, i; if (!pszQueryString) return NULL; lstrcpy(pszQueryString, ""); pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, uTag, FALSE); if (!pElement) return pszQueryString; uUIDsCount = L_DicomGetCountValue(hReqIdentifier, pElement); if (uUIDsCount > 1) { lstrcpy(pszQueryString, "("); } for (i = 0; i < uUIDsCount; i++) { pszUID = L_DicomGetStringValue(hReqIdentifier, pElement, i, 1); wsprintf(pszQueryString, "%s%s = '%s'", pszQueryString, pszFieldName ? pszFieldName : "", pszUID ? pszUID : ""); if (i != uUIDsCount - 1) { lstrcat(pszQueryString, " OR "); } } if (uUIDsCount > 1) { lstrcat(pszQueryString, ")"); } return pszQueryString; } BOOL IsRange(LPCSTR pszValue) { if (pszValue) { while (*pszValue) { if (*pszValue == '-') { return TRUE; } pszValue++; } } return FALSE; } VOID ConvertDicomDateToAccessDate(LPSTR pszDicomDate, LPSTR pszAccessDate) { char szTemp[8]; int iOffset; if (!pszDicomDate || !pszAccessDate) return; lstrcpy(pszAccessDate, ""); if (lstrlen(pszDicomDate) < 8) { return ; } iOffset = 0; lstrcpy(pszAccessDate, "#"); // Year lstrcpyn(szTemp, pszDicomDate + iOffset, 5); iOffset += 4; lstrcat(pszAccessDate, szTemp); lstrcat(pszAccessDate, "/"); // Month lstrcpyn(szTemp, pszDicomDate + iOffset, 3); iOffset += 2; lstrcat(pszAccessDate, szTemp); lstrcat(pszAccessDate, "/"); // Day lstrcpyn(szTemp, pszDicomDate + iOffset, 3); lstrcat(pszAccessDate, szTemp); lstrcat(pszAccessDate, "#"); } LPSTR GetQueryStringForDateRange(HDICOMDS hReqIdentifier, L_UINT32 uTag, LPCSTR pszFieldName, L_UINT uIndex, LPSTR pszQueryString) { pDICOMELEMENT pElement; char szSeps[] = "\\", szAccessDate[32]; char* pszToken, * pszBuffer; L_UINT uLocalIndex; if (!pszQueryString) return NULL; lstrcpy(pszQueryString, ""); pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, uTag, FALSE); if (!pElement) return pszQueryString; pszBuffer = (char*) malloc(pElement->nLength + 1); if (!pszBuffer) return pszQueryString; L_DicomGetBinaryValue(hReqIdentifier, pElement, pszBuffer, pElement->nLength); pszBuffer[pElement->nLength] = 0; uLocalIndex = 0; pszToken = strtok(pszBuffer, szSeps); while (pszToken) { // Is this the value we are looking for? if (uLocalIndex == uIndex) { if (IsRange(pszToken)) { /* These are the rules: 1. The date inside DICOM is formatted as yyyymmdd so "19930822" would represent August 22, 1993. 2. A string of the form " - " shall match all occurrences of dates which fall between and inclusive. 3. A string of the form "- " shall match all occurrences of dates prior to and including . 4. A string of the form " -" shall match all occurrences of and subsequent dates. */ // If it starts with a '-' then it's an upper range if (pszToken[0] == '-') { ConvertDicomDateToAccessDate(pszToken + 1 /*skip '-'*/, szAccessDate); wsprintf(pszQueryString, "(%s <= %s)", pszFieldName, szAccessDate); } // If it ends with a '-' then it's a lower range else if (pszToken[lstrlen(pszToken) - 1] == '-') { ConvertDicomDateToAccessDate(pszToken, szAccessDate); wsprintf(pszQueryString, "(%s >= %s)", pszFieldName, szAccessDate); } // It's a full range else { wsprintf(pszQueryString, "(%s BETWEEN ", pszFieldName); ConvertDicomDateToAccessDate(pszToken, szAccessDate); wsprintf(pszQueryString, "%s%s AND ", pszQueryString, szAccessDate); ConvertDicomDateToAccessDate(pszToken + 8 + 1, szAccessDate); wsprintf(pszQueryString, "%s%s)", pszQueryString, szAccessDate); } } else // No range! { ConvertDicomDateToAccessDate(pszToken, szAccessDate); wsprintf(pszQueryString, "(%s = %s)", pszFieldName, szAccessDate); } break; } uLocalIndex++; pszToken = strtok(NULL, szSeps); } free(pszBuffer); return pszQueryString; } VOID FindPatients(HWND hDlg, HDICOMNET hClient, HDICOMDS hReqIdentifier, L_UCHAR nPresentationID, L_UINT16 uMessageID, L_CHAR* pszClass, LPSTR pszUser) { pDICOMELEMENT pElement; L_CHAR* pszPatientID, * pszPatientName; char szQueryString[512], szBuffer[256], szLoggedFile[MAX_PATH]; HDICOMDS hRspIdentifier; DBHANDLES db; PATIENTSRECORDSET PatientsRS; STUDIESRECORDSET StudiesRS; SERIESRECORDSET SeriesRS; IMAGESRECORDSET ImagesRS; int iRelatedStudiesCount, iRelatedSeriesCount, iRelatedInstancesCount; L_INT nRet; if (!hClient || !hReqIdentifier) return; // The Unique Key: Patient ID pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_ID, FALSE); if (!pElement) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_MISSING_ATTRIBUTE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } pszPatientID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); // Required Keys: // Patient's Name pszPatientName = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_NAME, FALSE); if (pElement) { pszPatientName = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } // Form the query string lstrcpy(szQueryString, "SELECT * FROM Patients"); if (lstrlen(pszPatientID) || lstrlen(pszPatientName)) { lstrcat(szQueryString, " WHERE "); if (lstrlen(pszPatientID)) { wsprintf(szQueryString, "%sPatientID LIKE '%s'", szQueryString, PrepareForWCM(pszPatientID, szBuffer)); } if (lstrlen(pszPatientName)) { if (lstrlen(pszPatientID)) { lstrcat(szQueryString, " AND "); } wsprintf(szQueryString, "%sPatientName LIKE '%s'", szQueryString, PrepareForWCM(pszPatientName, szBuffer)); } } // The response Identifier hRspIdentifier = L_DicomCreateDS(gszTempFilesFolder); PrepareRspIdentifier(hRspIdentifier, hReqIdentifier, 1, TRUE); // Connect to the database if (!OpenDatabaseConnection(&db)) { L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // Look for matches if (!OpenPatientsRecordset(db.hDbc, &PatientsRS, szQueryString, TRUE)) { CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!PatientsRS.bEOF) { // The Unique Key SetKeyElement(hRspIdentifier, PatientsRS.szPatientID, TAG_PATIENT_ID); // Required Keys: if (PatientsRS.lPatientNameLenOrInd != SQL_NULL_DATA) SetKeyElement(hRspIdentifier, PatientsRS.szPatientName, TAG_PATIENT_NAME); // Optional Keys: if (PatientsRS.lPatientBirthDateInd != SQL_NULL_DATA) { SetTimeDateKeyElement(hRspIdentifier, &PatientsRS.PatientBirthDate, TAG_PATIENT_BIRTH_DATE, FALSE); } if (PatientsRS.lPatientBirthTimeInd != SQL_NULL_DATA) { SetTimeDateKeyElement(hRspIdentifier, &PatientsRS.PatientBirthTime, TAG_PATIENT_BIRTH_TIME, TRUE); } if (PatientsRS.lPatientSexLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, PatientsRS.szPatientSex, TAG_PATIENT_SEX); } if (PatientsRS.lEthnicGroupLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, PatientsRS.szEthnicGroup, TAG_ETHNIC_GROUP); } if (PatientsRS.lPatientCommentsLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, PatientsRS.szPatientComments, TAG_PATIENT_COMMENTS); } // The number of related studies, series, and instances iRelatedStudiesCount = iRelatedSeriesCount = iRelatedInstancesCount = 0; wsprintf(szQueryString, "SELECT * FROM Studies WHERE PatientID = '%s'", PatientsRS.szPatientID); if (!OpenStudiesRecordset(db.hDbc, &StudiesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &PatientsRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!StudiesRS.bEOF) { wsprintf(szQueryString, "SELECT * FROM Series WHERE StudyInstanceUID = '%s'", StudiesRS.szStudyInstanceUID); if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &StudiesRS, &PatientsRS, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!SeriesRS.bEOF) { wsprintf(szQueryString, "SELECT * FROM Images WHERE SeriesInstanceUID = '%s'", SeriesRS.szSeriesInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &SeriesRS, &StudiesRS, &PatientsRS, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { iRelatedInstancesCount++; if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, &SeriesRS, &StudiesRS, &PatientsRS); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&ImagesRS); iRelatedSeriesCount++; if (!GetNextRecord(&SeriesRS)) { WrapUpDatabase(&db, &SeriesRS, &StudiesRS, &PatientsRS, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&SeriesRS); iRelatedStudiesCount++; if (!GetNextRecord(&StudiesRS)) { WrapUpDatabase(&db, &StudiesRS, &PatientsRS, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&StudiesRS); wsprintf(szBuffer, "%d", iRelatedStudiesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_PATIENT_RELATED_STUDIES); wsprintf(szBuffer, "%d", iRelatedSeriesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_PATIENT_RELATED_SERIES); wsprintf(szBuffer, "%d", iRelatedInstancesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_PATIENT_RELATED_INSTANCES); // Here is a match nRet = L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PENDING, hRspIdentifier); if (nRet == DICOM_SUCCESS) { SaveSet(hRspIdentifier, TRUE, FALSE, szLoggedFile); wsprintf(szBuffer, "C-FIND-RESPONSE sent"); if (lstrlen(szLoggedFile)) { wsprintf(szBuffer, "%s and logged into: %s", szBuffer, szLoggedFile); } LogEvent(hDlg, pszUser, szBuffer); } if (!GetNextRecord(&PatientsRS)) { WrapUpDatabase(&db, &PatientsRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&PatientsRS); CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); // The final C-FIND-RSP L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_SUCCESS, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); } VOID FindStudies(HWND hDlg, HDICOMNET hClient, HDICOMDS hReqIdentifier, L_UCHAR nPresentationID, L_UINT16 uMessageID, L_CHAR* pszClass, LPSTR pszUser, BOOL bPatientRoot) { pDICOMELEMENT pElement; L_CHAR* pszPatientID, * pszStudyInstanceUID, * pszAccessionNumber, * pszStudyID; L_CHAR* pszPatientName; char szQueryString[2048], szBuffer[1024], szLoggedFile[MAX_PATH]; pVALUEDATE pvdStudyDate; pVALUETIME pvtStudyTime; BOOL bUseAND; HDICOMDS hRspIdentifier; DBHANDLES db; STUDIESRECORDSET StudiesRS; SERIESRECORDSET SeriesRS; IMAGESRECORDSET ImagesRS; int iRelatedSeriesCount, iRelatedInstancesCount; L_INT nRet; if (!hClient || !hReqIdentifier) return; // Patient ID // (Unique Key of the above level if Patient Root Query SOP Class) // (Required Key if Study Root Query SOP Class) pszPatientID = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_ID, FALSE); if (pElement) { pszPatientID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (bPatientRoot && !lstrlen(pszPatientID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // The Unique Key: Study Instance UID pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (!pElement) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_MISSING_ATTRIBUTE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } pszStudyInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); // Required Keys: // Study Date pvdStudyDate = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_DATE, FALSE); if (pElement) { pvdStudyDate = L_DicomGetDateValue(hReqIdentifier, pElement, 0, 1); } // Study Time pvtStudyTime = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_TIME, FALSE); if (pElement) { pvtStudyTime = L_DicomGetTimeValue(hReqIdentifier, pElement, 0, 1); } // Accession Number pszAccessionNumber = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_ACCESSION_NUMBER, FALSE); if (pElement) { pszAccessionNumber = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } // Study ID pszStudyID = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_ID, FALSE); if (pElement) { pszStudyID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } // If Study Root Query SOP Class: Patient Name and Patient ID (obtained above) pszPatientName = NULL; if (!bPatientRoot) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_NAME, FALSE); if (pElement) { pszPatientName = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } } // Form the query string lstrcpy(szQueryString, "SELECT * FROM Studies"); if (bPatientRoot) { wsprintf(szQueryString, "%s WHERE PatientID = '%s'", szQueryString, pszPatientID); } if (pszStudyInstanceUID || pvdStudyDate || pvtStudyTime || lstrlen(pszAccessionNumber) || lstrlen(pszStudyID) || lstrlen(pszPatientID) || lstrlen(pszPatientName)) { bUseAND = FALSE; if (!bPatientRoot) { lstrcat(szQueryString, " WHERE "); } else { bUseAND = TRUE; } if (pszStudyInstanceUID) { if (bUseAND) lstrcat(szQueryString, " AND "); lstrcat(szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_STUDY_INSTANCE_UID, "StudyInstanceUID", szBuffer)); bUseAND = TRUE; } if (pvdStudyDate) { if (bUseAND) lstrcat(szQueryString, " AND "); lstrcat(szQueryString, GetQueryStringForDateRange(hReqIdentifier, TAG_STUDY_DATE, "StudyDate", 0, szBuffer)); bUseAND = TRUE; } if (pvtStudyTime) { if (bUseAND) lstrcat(szQueryString, " AND "); wsprintf(szBuffer, "(HOUR(StudyTime) = %u AND MINUTE(StudyTime) = %u AND SECOND(StudyTime) = %u)", pvtStudyTime->nHours, pvtStudyTime->nMinutes, pvtStudyTime->nSeconds); lstrcat(szQueryString, szBuffer); bUseAND = TRUE; } if (lstrlen(pszAccessionNumber)) { if (bUseAND) lstrcat(szQueryString, " AND "); wsprintf(szQueryString, "%sAccessionNumber LIKE '%s'", szQueryString, PrepareForWCM(pszAccessionNumber, szBuffer)); bUseAND = TRUE; } if (lstrlen(pszStudyID)) { if (bUseAND) lstrcat(szQueryString, " AND "); wsprintf(szQueryString, "%sStudyID LIKE '%s'", szQueryString, PrepareForWCM(pszStudyID, szBuffer)); bUseAND = TRUE; } if (!bPatientRoot) { if (lstrlen(pszPatientID)) { if (bUseAND) lstrcat(szQueryString, " AND "); wsprintf(szQueryString, "%sPatientID LIKE '%s'", szQueryString, PrepareForWCM(pszPatientID, szBuffer)); bUseAND = TRUE; } if (lstrlen(pszPatientName)) { if (bUseAND) lstrcat(szQueryString, " AND "); wsprintf(szQueryString, "%sPatientName LIKE '%s'", szQueryString, PrepareForWCM(pszPatientName, szBuffer)); } } } // The response Identifier hRspIdentifier = L_DicomCreateDS(gszTempFilesFolder); PrepareRspIdentifier(hRspIdentifier, hReqIdentifier, 2, bPatientRoot); if (bPatientRoot) { SetKeyElement(hRspIdentifier, pszPatientID, TAG_PATIENT_ID); } // Connect to the database if (!OpenDatabaseConnection(&db)) { L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // Look for matches if (!OpenStudiesRecordset(db.hDbc, &StudiesRS, szQueryString, TRUE)) { CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!StudiesRS.bEOF) { // The Unique Key SetKeyElement(hRspIdentifier, StudiesRS.szStudyInstanceUID, TAG_STUDY_INSTANCE_UID); // Required Keys: if (StudiesRS.lStudyDateInd != SQL_NULL_DATA) { SetTimeDateKeyElement(hRspIdentifier, &StudiesRS.StudyDate, TAG_STUDY_DATE, FALSE); } if (StudiesRS.lStudyTimeInd != SQL_NULL_DATA) { SetTimeDateKeyElement(hRspIdentifier, &StudiesRS.StudyTime, TAG_STUDY_TIME, TRUE); } if (StudiesRS.lAccessionNumberLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, StudiesRS.szAccessionNumber, TAG_ACCESSION_NUMBER); } if (StudiesRS.lStudyIDLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, StudiesRS.szStudyID, TAG_STUDY_ID); } if (!bPatientRoot) { if (StudiesRS.lPatientNameLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, StudiesRS.szPatientName, TAG_PATIENT_NAME); } if (StudiesRS.lPatientIDLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, StudiesRS.szPatientID, TAG_PATIENT_ID); } } // Optional Keys: if (StudiesRS.lStudyDescriptionLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, StudiesRS.szStudyDescription, TAG_STUDY_DESCRIPTION); } // The number of related series and instances iRelatedSeriesCount = iRelatedInstancesCount = 0; wsprintf(szQueryString, "SELECT * FROM Series WHERE StudyInstanceUID = '%s'", StudiesRS.szStudyInstanceUID); if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &StudiesRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!SeriesRS.bEOF) { wsprintf(szQueryString, "SELECT * FROM Images WHERE SeriesInstanceUID = '%s'", SeriesRS.szSeriesInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &SeriesRS, &StudiesRS, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { iRelatedInstancesCount++; if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, &SeriesRS, &StudiesRS, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&ImagesRS); iRelatedSeriesCount++; if (!GetNextRecord(&SeriesRS)) { WrapUpDatabase(&db, &SeriesRS, &StudiesRS, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&SeriesRS); wsprintf(szBuffer, "%d", iRelatedSeriesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_STUDY_RELATED_SERIES); wsprintf(szBuffer, "%d", iRelatedInstancesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_STUDY_RELATED_INSTANCES); // Here is a match nRet = L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PENDING, hRspIdentifier); if (nRet == DICOM_SUCCESS) { SaveSet(hRspIdentifier, TRUE, FALSE, szLoggedFile); wsprintf(szBuffer, "C-FIND-RESPONSE sent"); if (lstrlen(szLoggedFile)) { wsprintf(szBuffer, "%s and logged into: %s", szBuffer, szLoggedFile); } LogEvent(hDlg, pszUser, szBuffer); } if (!GetNextRecord(&StudiesRS)) { WrapUpDatabase(&db, &StudiesRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&StudiesRS); CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); // The final C-FIND-RSP L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_SUCCESS, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); } VOID FindSeries(HWND hDlg, HDICOMNET hClient, HDICOMDS hReqIdentifier, L_UCHAR nPresentationID, L_UINT16 uMessageID, L_CHAR* pszClass, LPSTR pszUser, BOOL bPatientRoot) { pDICOMELEMENT pElement; L_CHAR* pszPatientID, * pszStudyInstanceUID, * pszSeriesInstanceUID, * pszModality; char szSeriesNumber[64], szQueryString[2048], szBuffer[1024], szLoggedFile[MAX_PATH]; L_INT32* pnValue; HDICOMDS hRspIdentifier; DBHANDLES db; SERIESRECORDSET SeriesRS; IMAGESRECORDSET ImagesRS; int iRelatedInstancesCount; L_INT nRet; if (!hClient || !hReqIdentifier) return; // Unique Keys of the above levels: // Patient ID (if Patient Root Query SOP Class) pszPatientID = NULL; if (bPatientRoot) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_ID, FALSE); if (pElement) { pszPatientID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszPatientID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } // Study Instance UID pszStudyInstanceUID = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (pElement) { pszStudyInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszStudyInstanceUID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // The Unique Key: Series Instance UID pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (!pElement) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_MISSING_ATTRIBUTE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } pszSeriesInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); // Required Keys: // Modality pszModality = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_MODALITY, FALSE); if (pElement) { pszModality = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } // Series Number lstrcpy(szSeriesNumber, ""); pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SERIES_NUMBER, FALSE); if (pElement) { pnValue = L_DicomGetLongValue(hReqIdentifier, pElement, 0, 1); if (pnValue) { itoa(*pnValue, szSeriesNumber, 10); } } // Form the query string lstrcpy(szQueryString, "SELECT * FROM Series WHERE "); if (bPatientRoot) { wsprintf(szQueryString, "%sPatientID = '%s' AND ", szQueryString, pszPatientID); } wsprintf(szQueryString, "%sStudyInstanceUID = '%s'", szQueryString, pszStudyInstanceUID); if (pszSeriesInstanceUID || lstrlen(pszModality) || lstrlen(szSeriesNumber)) { if (pszSeriesInstanceUID) { wsprintf(szQueryString, "%s AND %s", szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID", szBuffer)); } if (lstrlen(pszModality)) { wsprintf(szQueryString, "%s AND Modality LIKE '%s'", szQueryString, PrepareForWCM(pszModality, szBuffer)); } if (lstrlen(szSeriesNumber)) { wsprintf(szQueryString, "%s AND SeriesNumber = %s", szQueryString, szSeriesNumber); } } // The response Identifier hRspIdentifier = L_DicomCreateDS(gszTempFilesFolder); PrepareRspIdentifier(hRspIdentifier, hReqIdentifier, 3, bPatientRoot); if (bPatientRoot) { SetKeyElement(hRspIdentifier, pszPatientID, TAG_PATIENT_ID); } SetKeyElement(hRspIdentifier, pszStudyInstanceUID, TAG_STUDY_INSTANCE_UID); // Connect to the database if (!OpenDatabaseConnection(&db)) { L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // Look for matches if (!OpenSeriesRecordset(db.hDbc, &SeriesRS, szQueryString, TRUE)) { CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!SeriesRS.bEOF) { // The Unique Key SetKeyElement(hRspIdentifier, SeriesRS.szSeriesInstanceUID, TAG_SERIES_INSTANCE_UID); // Required Keys: if (SeriesRS.lModalityLenOrInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, SeriesRS.szModality, TAG_MODALITY); } if (SeriesRS.lSeriesNumberInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, ltoa(SeriesRS.lSeriesNumber, szSeriesNumber, 10), TAG_SERIES_NUMBER); } // Optional Keys: // The number of related instances iRelatedInstancesCount = 0; wsprintf(szQueryString, "SELECT * FROM Images WHERE SeriesInstanceUID = '%s'", SeriesRS.szSeriesInstanceUID); if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, TRUE)) { WrapUpDatabase(&db, &SeriesRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { iRelatedInstancesCount++; if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, &SeriesRS, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&ImagesRS); wsprintf(szBuffer, "%d", iRelatedInstancesCount); SetKeyElement(hRspIdentifier, szBuffer, TAG_NUMBER_OF_SERIES_RELATED_INSTANCES); // Here is a match nRet = L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PENDING, hRspIdentifier); if (nRet == DICOM_SUCCESS) { SaveSet(hRspIdentifier, TRUE, FALSE, szLoggedFile); wsprintf(szBuffer, "C-FIND-RESPONSE sent"); if (lstrlen(szLoggedFile)) { wsprintf(szBuffer, "%s and logged into: %s", szBuffer, szLoggedFile); } LogEvent(hDlg, pszUser, szBuffer); } if (!GetNextRecord(&SeriesRS)) { WrapUpDatabase(&db, &SeriesRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&SeriesRS); CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); // The final C-FIND-RSP L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_SUCCESS, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); } VOID FindImages(HWND hDlg, HDICOMNET hClient, HDICOMDS hReqIdentifier, L_UCHAR nPresentationID, L_UINT16 uMessageID, L_CHAR* pszClass, LPSTR pszUser, BOOL bPatientRoot) { pDICOMELEMENT pElement; L_CHAR* pszPatientID, * pszStudyInstanceUID, * pszSeriesInstanceUID, * pszSOPInstanceUID; char szInstanceNumber[64], szQueryString[2048], szBuffer[1024], szLoggedFile[MAX_PATH]; L_INT32* pnValue; HDICOMDS hRspIdentifier; DBHANDLES db; IMAGESRECORDSET ImagesRS; L_INT nRet; if (!hClient || !hReqIdentifier) return; // Unique Keys of the above levels: // Patient ID (if Patient Root Query SOP Class) pszPatientID = NULL; if (bPatientRoot) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_ID, FALSE); if (pElement) { pszPatientID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszPatientID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } // Study Instance UID pszStudyInstanceUID = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (pElement) { pszStudyInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszStudyInstanceUID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // Series Instance UID pszSeriesInstanceUID = NULL; pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (pElement) { pszSeriesInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszSeriesInstanceUID)) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // The Unique Key: SOP Instance UID pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SOP_INSTANCE_UID, FALSE); if (!pElement) { L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_MISSING_ATTRIBUTE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } pszSOPInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); // Required Keys: // Instance Number lstrcpy(szInstanceNumber, ""); pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_INSTANCE_NUMBER, FALSE); if (pElement) { pnValue = L_DicomGetLongValue(hReqIdentifier, pElement, 0, 1); if (pnValue) { itoa(*pnValue, szInstanceNumber, 10); } } // Form the query string lstrcpy(szQueryString, "SELECT * FROM Images WHERE "); if (bPatientRoot) { wsprintf(szQueryString, "%sPatientID = '%s' AND ", szQueryString, pszPatientID); } wsprintf(szQueryString, "%sStudyInstanceUID = '%s' AND ", szQueryString, pszStudyInstanceUID); wsprintf(szQueryString, "%sSeriesInstanceUID = '%s'", szQueryString, pszSeriesInstanceUID); if (pszSOPInstanceUID || lstrlen(szInstanceNumber)) { if (pszSOPInstanceUID) { wsprintf(szQueryString, "%s AND ", szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_SOP_INSTANCE_UID, "SOPInstanceUID", szBuffer)); } if (lstrlen(szInstanceNumber)) { wsprintf(szQueryString, "%s AND InstanceNumber = %s", szQueryString, szInstanceNumber); } } // The response Identifier hRspIdentifier = L_DicomCreateDS(gszTempFilesFolder); PrepareRspIdentifier(hRspIdentifier, hReqIdentifier, 4, bPatientRoot); if (bPatientRoot) { SetKeyElement(hRspIdentifier, pszPatientID, TAG_PATIENT_ID); } SetKeyElement(hRspIdentifier, pszStudyInstanceUID, TAG_STUDY_INSTANCE_UID); SetKeyElement(hRspIdentifier, pszSeriesInstanceUID, TAG_SERIES_INSTANCE_UID); // Connect to the database if (!OpenDatabaseConnection(&db)) { L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } // Look for matches if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, TRUE)) { CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { // The Unique Key SetKeyElement(hRspIdentifier, ImagesRS.szSOPInstanceUID, TAG_SOP_INSTANCE_UID); // Required Keys: if (ImagesRS.lInstanceNumberInd != SQL_NULL_DATA) { SetKeyElement(hRspIdentifier, ltoa(ImagesRS.lInstanceNumber, szInstanceNumber, 10), TAG_INSTANCE_NUMBER); } // Here is a match nRet = L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PENDING, hRspIdentifier); if (nRet == DICOM_SUCCESS) { SaveSet(hRspIdentifier, TRUE, FALSE, szLoggedFile); wsprintf(szBuffer, "C-FIND-RESPONSE sent"); if (lstrlen(szLoggedFile)) { wsprintf(szBuffer, "%s and logged into: %s", szBuffer, szLoggedFile); } LogEvent(hDlg, pszUser, szBuffer); } if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); L_DicomFreeDS(hRspIdentifier); L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_PROCESSING_FAILURE, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); return; } } CloseRecordset(&ImagesRS); CloseDatabaseConnection(&db); L_DicomFreeDS(hRspIdentifier); // The final C-FIND-RSP L_DicomSendCFindResponse(hClient, nPresentationID, uMessageID, pszClass, COMMAND_STATUS_SUCCESS, NULL); LogEvent(hDlg, pszUser, "C-FIND-RESPONSE sent"); } // iQRLevel: (1: Ptn), (2: Std), (3: Srs), (4: Img) VOID MoveImages(HWND hDlg, HDICOMDS hReqIdentifier, LPSTR pszMoveDstIP, L_UINT uMoveDstPort, int iQRLevel, BOOL bPatientRoot, LPSTR pszUser) { pDICOMELEMENT pElement; L_CHAR* pszPatientID, * pszStudyInstanceUID, * pszSeriesInstanceUID, * pszSOPInstanceUID; L_CHAR szQueryString[2048], szBuffer[1024]; DBHANDLES db; IMAGESRECORDSET ImagesRS; int iIndex, iSize; if (!hReqIdentifier) return; // Unique Keys: // Patient ID (if Patient Root Q/R SOP Class) pszPatientID = NULL; if (bPatientRoot) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_PATIENT_ID, FALSE); if (pElement) { pszPatientID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszPatientID)) { L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } // Study Instance UID pszStudyInstanceUID = NULL; if (iQRLevel >= 2) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_STUDY_INSTANCE_UID, FALSE); if (pElement) { pszStudyInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszStudyInstanceUID)) { L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } // Series Instance UID pszSeriesInstanceUID = NULL; if (iQRLevel >= 3) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SERIES_INSTANCE_UID, FALSE); if (pElement) { pszSeriesInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszSeriesInstanceUID)) { L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } // SOP Instance UID pszSOPInstanceUID = NULL; if (iQRLevel >= 4) { pElement = L_DicomFindFirstElement(hReqIdentifier, NULL, TAG_SOP_INSTANCE_UID, FALSE); if (pElement) { pszSOPInstanceUID = L_DicomGetStringValue(hReqIdentifier, pElement, 0, 1); } if (!lstrlen(pszSOPInstanceUID)) { L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, (L_UINT16) ((pElement == NULL) ? COMMAND_STATUS_MISSING_ATTRIBUTE : COMMAND_STATUS_MISSING_ATTRIBUTE_VALUE), 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } // Form the query string lstrcpy(szQueryString, "SELECT * FROM Images WHERE "); if (bPatientRoot) { wsprintf(szQueryString, "%sPatientID = '%s'", szQueryString, pszPatientID); } if (iQRLevel >= 2) { if (bPatientRoot) lstrcat(szQueryString, " AND "); if (iQRLevel != 2) { wsprintf(szQueryString, "%sStudyInstanceUID = '%s'", szQueryString, pszStudyInstanceUID); } else { lstrcat(szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_STUDY_INSTANCE_UID, "StudyInstanceUID", szBuffer)); } } if (iQRLevel >= 3) { lstrcat(szQueryString, " AND "); if (iQRLevel != 3) { wsprintf(szQueryString, "%sSeriesInstanceUID = '%s'", szQueryString, pszSeriesInstanceUID); } else { lstrcat(szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_SERIES_INSTANCE_UID, "SeriesInstanceUID", szBuffer)); } } if (iQRLevel >= 4) { lstrcat(szQueryString, " AND "); lstrcat(szQueryString, GetQueryStringForUIDs(hReqIdentifier, TAG_SOP_INSTANCE_UID, "SOPInstanceUID", szBuffer)); } // Connect to the database if (!OpenDatabaseConnection(&db)) { L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } if (gpMoveMatches) { free(gpMoveMatches); gpMoveMatches = NULL; } gnMatchesCount = 0; // Look for matches if (!OpenImagesRecordset(db.hDbc, &ImagesRS, szQueryString, FALSE)) { CloseDatabaseConnection(&db); L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { gnMatchesCount++; if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); gnMatchesCount = 0; L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } if (gnMatchesCount) { gpMoveMatches = (pMOVEMATCHES) malloc(gnMatchesCount * sizeof(MOVEMATCHES)); if (!gpMoveMatches) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); gnMatchesCount = 0; L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } iIndex = 0; if (!GetFirstRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); free(gpMoveMatches); gpMoveMatches = NULL; gnMatchesCount = 0; L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } while (!ImagesRS.bEOF) { // SOP Class UID iSize = sizeof(gpMoveMatches[iIndex].szSOPClassUID) / sizeof(gpMoveMatches[iIndex].szSOPClassUID[0]); lstrcpyn(gpMoveMatches[iIndex].szSOPClassUID, ImagesRS.szSOPClassUID, iSize); // Transfer Syntax UID iSize = sizeof(gpMoveMatches[iIndex].szTransferSyntaxUID) / sizeof(gpMoveMatches[iIndex].szTransferSyntaxUID[0]); lstrcpyn(gpMoveMatches[iIndex].szTransferSyntaxUID, ImagesRS.szTransferSyntaxUID, iSize); // Referenced File if (ImagesRS.lReferencedFileLenOrInd != SQL_NULL_DATA) { iSize = sizeof(gpMoveMatches[iIndex].szReferencedFile) / sizeof(gpMoveMatches[iIndex].szReferencedFile[0]); lstrcpyn(gpMoveMatches[iIndex].szReferencedFile, ImagesRS.szReferencedFile, iSize); } else { lstrcpy(gpMoveMatches[iIndex].szReferencedFile, ""); } iIndex++; if (!GetNextRecord(&ImagesRS)) { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); free(gpMoveMatches); gpMoveMatches = NULL; gnMatchesCount = 0; L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_PROCESSING_FAILURE, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } } CloseRecordset(&ImagesRS); } else { WrapUpDatabase(&db, &ImagesRS, NULL, NULL, NULL); L_DicomSendCMoveResponse(ghMoveNet, gnMovePresentationID, guMoveMessageID, gszMoveClass, COMMAND_STATUS_SUCCESS, 0, 0, 0, 0, NULL); LogEvent(hDlg, pszUser, "C-MOVE-RESPONSE sent"); return; } CloseDatabaseConnection(&db); gnSuccessfulSubOperations = 0; gnFailedSubOperations = 0; gnWarningSubOperations = 0; guStoreMessageID = 1; gnMatchIndex = -1; // Connect to the Move Destination AE L_DicomConnect(ghClient, "", 0, pszMoveDstIP, uMoveDstPort); }