/*---------------------------------------------------------------------- file: pp.c - property page ----------------------------------------------------------------------*/ #include "cyyports.h" #include "pp.h" #include #include //TCHAR m_szDevMgrHelp[] = _T("devmgr.hlp"); TCHAR m_szCyycoinsHelp[] = _T("cyycoins.chm"); TCHAR y_szNumOfPorts[] = TEXT("NumOfPorts"); const DWORD HelpIDs[]= { IDC_STATIC, IDH_CYYCOINS_NOHELP, IDC_STATIC_BOARD_DETAILS, IDH_CYYCOINS_NOHELP, IDC_STATIC_SETTINGS, IDH_CYYCOINS_NOHELP, IDC_NUM_PORTS, IDH_CYYCOINS_NUM_PORTS, PP_NUM_PORTS, IDH_CYYCOINS_NUM_PORTS, IDC_START_COM, IDH_CYYCOINS_START_COM, PP_START_COM, IDH_CYYCOINS_START_COM, IDC_RESTORE_DEFAULTS, IDH_CYYCOINS_RESTORE_DEFAULTS, IDC_BUS_TYPE, IDH_CYYCOINS_BUS_TYPE, PP_BUS_TYPE, IDH_CYYCOINS_BUS_TYPE, IDC_CONFIGURATION, IDH_CYYCOINS_CONFIGURATION, PP_CONFIGURATION, IDH_CYYCOINS_CONFIGURATION, IDC_MODEL, IDH_CYYCOINS_MODEL, PP_MODEL, IDH_CYYCOINS_MODEL, 0, 0 }; void InitPortParams( IN OUT PPORT_PARAMS Params, IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData ) { SP_DEVINFO_LIST_DETAIL_DATA detailData; HCOMDB hComDB; DWORD maxPortsReported; //DbgOut(TEXT("InitPortParams\n")); ZeroMemory(Params, sizeof(PORT_PARAMS)); Params->DeviceInfoSet = DeviceInfoSet; Params->DeviceInfoData = DeviceInfoData; // Allocate and initialize PortUsage matrix ComDBOpen(&hComDB); if (hComDB != INVALID_HANDLE_VALUE) { ComDBGetCurrentPortUsage(hComDB, NULL, 0, CDB_REPORT_BYTES, &maxPortsReported); //#if DBG //{ // TCHAR buf[500]; // wsprintf(buf, TEXT("maxPortsReported %d\n"),maxPortsReported); // DbgOut(buf); //} //#endif if (maxPortsReported != 0) { Params->ShowStartCom = TRUE; //Params->PortUsage = (PBYTE) LocalAlloc(LPTR,maxPortsReported/8); if (maxPortsReported > MAX_COM_PORT) { Params->PortUsageSize = maxPortsReported; } else { Params->PortUsageSize = MAX_COM_PORT; } Params->PortUsage = (PBYTE) LocalAlloc(LPTR,Params->PortUsageSize/8); if (Params->PortUsage != NULL) { Params->PortUsageSize = maxPortsReported/8; ComDBGetCurrentPortUsage(hComDB, Params->PortUsage, Params->PortUsageSize, CDB_REPORT_BITS, &maxPortsReported ); } } ComDBClose(hComDB); } else { // This happens if we don't have sufficient security privileges. // GetLastError returns 0 here!!! Some bug in ComDBOpen. DbgOut(TEXT("cyycoins ComDBOpen failed.\n")); } // // See if we are being invoked locally or over the network. If over the net, // then disable all possible changes. // detailData.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA); if (SetupDiGetDeviceInfoListDetail(DeviceInfoSet, &detailData) && detailData.RemoteMachineHandle != NULL) { Params->ShowStartCom = FALSE; } } HPROPSHEETPAGE InitSettingsPage(PROPSHEETPAGE * psp, OUT PPORT_PARAMS Params) { // // Add the Port Settings property page // psp->dwSize = sizeof(PROPSHEETPAGE); psp->dwFlags = PSP_USECALLBACK; // | PSP_HASHELP; psp->hInstance = g_hInst; psp->pszTemplate = MAKEINTRESOURCE(DLG_PP_PORTSETTINGS); // // following points to the dlg window proc // psp->pfnDlgProc = PortSettingsDlgProc; psp->lParam = (LPARAM) Params; // // following points to some control callback of the dlg window proc // psp->pfnCallback = PortSettingsDlgCallback; // // allocate our "Ports Setting" sheet // return CreatePropertySheetPage(psp); } /*++ Routine Description: CyclomyPropPageProvider Entry-point for adding additional device manager property sheet pages. Registry specifies this routine under Control\Class\PortNode::EnumPropPage32="msports.dll,thisproc" entry. This entry-point gets called only when the Device Manager asks for additional property pages. Arguments: Info - points to PROPSHEETPAGE_REQUEST, see setupapi.h AddFunc - function ptr to call to add sheet. Lparam - add sheet functions private data handle. Return Value: BOOL: FALSE if pages could not be added, TRUE on success --*/ BOOL APIENTRY CyclomyPropPageProvider(LPVOID Info, LPFNADDPROPSHEETPAGE AddFunc, LPARAM Lparam ) { PSP_PROPSHEETPAGE_REQUEST pprPropPageRequest; PROPSHEETPAGE psp; HPROPSHEETPAGE hpsp; PPORT_PARAMS params = NULL; //DbgOut(TEXT("cyycoins CyclomyPropPageProvider entry\n")); pprPropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) Info; // // Allocate and zero out memory for the struct that will contain // page specific data // params = (PPORT_PARAMS) LocalAlloc(LPTR, sizeof(PORT_PARAMS)); //****************************************************************** // TEST ERROR // if (params) // LocalFree(params); // params = NULL; // //****************************************************************** if (!params) { ErrMemDlg(GetFocus()); return FALSE; } if (pprPropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) { InitPortParams(params, pprPropPageRequest->DeviceInfoSet, pprPropPageRequest->DeviceInfoData); hpsp = InitSettingsPage(&psp, params); if (!hpsp) { return FALSE; } if (!(*AddFunc)(hpsp, Lparam)) { DestroyPropertySheetPage(hpsp); return FALSE; } } return TRUE; } /* CyclomyPropPageProvider */ UINT CALLBACK PortSettingsDlgCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) { PPORT_PARAMS params; switch (uMsg) { case PSPCB_CREATE: return TRUE; // return TRUE to continue with creation of page case PSPCB_RELEASE: //DbgOut(TEXT("PortSettingsDlgCallBack PSPCB_RELEASE\n")); params = (PPORT_PARAMS) ppsp->lParam; if (params->PortUsage) { LocalFree(params->PortUsage); } LocalFree(params); return 0; // return value ignored default: break; } return TRUE; } void Port_OnCommand( HWND DialogHwnd, int ControlId, HWND ControlHwnd, UINT NotifyCode ); BOOL Port_OnContextMenu( HWND HwndControl, WORD Xpos, WORD Ypos ); void Port_OnHelp( HWND DialogHwnd, LPHELPINFO HelpInfo ); BOOL Port_OnInitDialog( HWND DialogHwnd, HWND FocusHwnd, LPARAM Lparam ); BOOL Port_OnNotify( HWND DialogHwnd, LPNMHDR NmHdr ); /*++ Routine Description: PortSettingsDlgProc The windows control function for the Port Settings properties window Arguments: hDlg, uMessage, wParam, lParam: standard windows DlgProc parameters Return Value: BOOL: FALSE if function fails, TRUE if function passes --*/ INT_PTR APIENTRY PortSettingsDlgProc(IN HWND hDlg, IN UINT uMessage, IN WPARAM wParam, IN LPARAM lParam) { switch(uMessage) { case WM_COMMAND: Port_OnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam)); break; case WM_CONTEXTMENU: return Port_OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam)); case WM_HELP: Port_OnHelp(hDlg, (LPHELPINFO) lParam); break; case WM_INITDIALOG: return Port_OnInitDialog(hDlg, (HWND)wParam, lParam); case WM_NOTIFY: return Port_OnNotify(hDlg, (NMHDR *)lParam); } return FALSE; } /* PortSettingsDialogProc */ void Port_OnRestoreDefaultsClicked( HWND DialogHwnd, PPORT_PARAMS Params ) { RestoreDefaults(DialogHwnd, Params); PropSheet_Changed(GetParent(DialogHwnd), DialogHwnd); } void Port_OnCommand( HWND DialogHwnd, int ControlId, HWND ControlHwnd, UINT NotifyCode ) { PPORT_PARAMS params = (PPORT_PARAMS)GetWindowLongPtr(DialogHwnd, DWLP_USER); if (NotifyCode == CBN_SELCHANGE) { PropSheet_Changed(GetParent(DialogHwnd), DialogHwnd); } else { switch (ControlId) { //case IDC_ADVANCED: // Port_OnAdvancedClicked(DialogHwnd, params); // break; // case IDC_RESTORE_DEFAULTS: Port_OnRestoreDefaultsClicked(DialogHwnd, params); break; // // Because this is a prop sheet, we should never get this. // All notifications for ctrols outside of the sheet come through // WM_NOTIFY // case IDCANCEL: EndDialog(DialogHwnd, 0); return; } } } BOOL Port_OnContextMenu( HWND HwndControl, WORD Xpos, WORD Ypos ) { // WinHelp(HwndControl, // m_szCyycoinsHelp, //m_szDevMgrHelp, // HELP_CONTEXTMENU, // (ULONG_PTR) HelpIDs); HtmlHelp(HwndControl, m_szCyycoinsHelp, HH_TP_HELP_CONTEXTMENU, (ULONG_PTR) HelpIDs); return FALSE; } void Port_OnHelp( HWND DialogHwnd, LPHELPINFO HelpInfo ) { if (HelpInfo->iContextType == HELPINFO_WINDOW) { // WinHelp((HWND) HelpInfo->hItemHandle, // m_szCyycoinsHelp, //m_szDevMgrHelp, // HELP_WM_HELP, // (ULONG_PTR) HelpIDs); HtmlHelp((HWND) HelpInfo->hItemHandle, m_szCyycoinsHelp, HH_TP_HELP_WM_HELP, (ULONG_PTR) HelpIDs); } } BOOL Port_OnInitDialog( HWND DialogHwnd, HWND FocusHwnd, LPARAM Lparam ) { PPORT_PARAMS params; DWORD dwError; //DbgOut(TEXT("Port_OnInitDialog\n")); // // on WM_INITDIALOG call, lParam points to the property // sheet page. // // The lParam field in the property sheet page struct is set by the // caller. When I created the property sheet, I passed in a pointer // to a struct containing information about the device. Save this in // the user window long so I can access it on later messages. // params = (PPORT_PARAMS) ((LPPROPSHEETPAGE)Lparam)->lParam; SetWindowLongPtr(DialogHwnd, DWLP_USER, (ULONG_PTR) params); // Display board details FillNumberOfPortsText(DialogHwnd,params); FillModelAndBusTypeText(DialogHwnd,params); // // Set up the combo box with choices // if (params->ShowStartCom) { ComDBOpen(¶ms->hComDB); params->ShowStartCom = FillStartComCb(DialogHwnd, params); if (params->hComDB != HCOMDB_INVALID_HANDLE_VALUE) { ComDBClose(params->hComDB); } } else { EnableWindow(GetDlgItem(DialogHwnd, PP_START_COM), FALSE); EnableWindow(GetDlgItem(DialogHwnd, IDC_START_COM), FALSE); } return TRUE; // No need for us to set the focus. } BOOL Port_OnNotify( HWND DialogHwnd, LPNMHDR NmHdr ) { PPORT_PARAMS params = (PPORT_PARAMS)GetWindowLongPtr(DialogHwnd, DWLP_USER); switch (NmHdr->code) { // // Sent when the user clicks on Apply OR OK !! // case PSN_APPLY: //DbgOut(TEXT("Port_OnNotify PSN_APPLY\n")); // // Write out the com port options to the registry // if (SavePortSettingsDlg(DialogHwnd, params)) { SetWindowLongPtr(DialogHwnd, DWLP_MSGRESULT, PSNRET_NOERROR); } else { SetWindowLongPtr(DialogHwnd, DWLP_MSGRESULT, PSNRET_INVALID); } return TRUE; default: //DbgOut(TEXT("Port_OnNotify default\n")); return FALSE; } } ULONG FillModelAndBusTypeText( IN HWND DialogHwnd, IN PPORT_PARAMS Params ) { TCHAR szHardwareId[LINE_LEN]; PTCHAR szCharPtr; HWND detailHwnd; TCHAR szBusType[10]; TCHAR szConfiguration[10]; TCHAR szModel[10]; DWORD dataType; ZeroMemory(szBusType,sizeof(szBusType)); ZeroMemory(szConfiguration,sizeof(szConfiguration)); ZeroMemory(szModel,sizeof(szModel)); if (SetupDiGetDeviceRegistryProperty(Params->DeviceInfoSet, Params->DeviceInfoData, SPDRP_HARDWAREID, &dataType, (PBYTE) szHardwareId, sizeof(szHardwareId), NULL)) { szCharPtr = szHardwareId; while (*szCharPtr) { if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0100&SUBSYS_0100120E"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0100&SUBSYS_0100120E"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Below 1MB")); wsprintf(szModel, TEXT("YeP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0101&SUBSYS_0100120E"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0101&SUBSYS_0100120E"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Above 1MB")); wsprintf(szModel, TEXT("YeP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0100"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0100"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Below 1MB")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0101"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0101"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Above 1MB")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0102"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0102"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Below 1MB")); wsprintf(szModel, TEXT("4YP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0103"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0103"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Above 1MB")); wsprintf(szModel, TEXT("4YP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0104"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0104"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Below 1MB")); wsprintf(szModel, TEXT("8YP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("PCI\\VEN_120E&DEV_0105"), _tcslen(TEXT("PCI\\VEN_120E&DEV_0105"))) == 0) { wsprintf(szBusType, TEXT("PCI")); wsprintf(szConfiguration, TEXT("Above 1MB")); wsprintf(szModel, TEXT("8YP")); break; } else if (_tcsnicmp(szCharPtr, TEXT("YISA"), _tcslen(TEXT("YISA"))) == 0) { wsprintf(szBusType, TEXT("ISA")); } break; szCharPtr = szCharPtr + _tcslen(szCharPtr) + 1; } if (*szBusType) { detailHwnd = GetDlgItem(DialogHwnd, PP_BUS_TYPE); SetWindowText(detailHwnd,szBusType); } if (*szConfiguration) { detailHwnd = GetDlgItem(DialogHwnd, IDC_CONFIGURATION); SetWindowText(detailHwnd,TEXT("Configuration:")); detailHwnd = GetDlgItem(DialogHwnd, PP_CONFIGURATION); SetWindowText(detailHwnd,szConfiguration); } if (*szModel) { detailHwnd = GetDlgItem(DialogHwnd, IDC_MODEL); SetWindowText(detailHwnd,TEXT("Model:")); detailHwnd = GetDlgItem(DialogHwnd, PP_MODEL); SetWindowText(detailHwnd,szModel); } } return ERROR_SUCCESS; } ULONG FillNumberOfPortsText( IN HWND DialogHwnd, IN PPORT_PARAMS Params ) { HKEY hDeviceKey; DWORD err,numOfPortsSize,numOfPorts; HWND numportHwnd; TCHAR szText[10]; err = ERROR_SUCCESS; if((hDeviceKey = SetupDiOpenDevRegKey(Params->DeviceInfoSet, Params->DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)) == INVALID_HANDLE_VALUE) { err = GetLastError(); goto FillNPortsExit; } numOfPortsSize = sizeof(numOfPorts); err = RegQueryValueEx(hDeviceKey, y_szNumOfPorts, NULL, NULL, (PBYTE)&numOfPorts, &numOfPortsSize ); //******************************************************** // TEST ERROR // err=ERROR_REGISTRY_CORRUPT; //******************************************************** RegCloseKey(hDeviceKey); if(err != ERROR_SUCCESS) { goto FillNPortsExit; } numportHwnd = GetDlgItem(DialogHwnd, PP_NUM_PORTS); wsprintf(szText, TEXT("%d"),numOfPorts); SetWindowText(numportHwnd,szText); FillNPortsExit: //if (err != ERROR_SUCCESS) { // MyMessageBoxWithErr(DialogHwnd,IDS_NUM_PORTS_DISABLED,IDS_CYCLOMY,MB_ICONWARNING,err); //} return err; } /*++ Routine Description: FillStartComCb fill in the Port Name combo box selection with a list of possible un-used portnames Arguments: poppOurPropParams: where to save the data to hDlg: address of the window Return Value: BOOL: TRUE if StartCom CB displayed with no errors --*/ BOOL FillStartComCb( HWND ParentHwnd, PPORT_PARAMS Params ) { int i, j, nEntries; DWORD nCurPortNum = 0; DWORD nCom; // Changed from int to DWORD (Fanny) DWORD dwError; TCHAR szCom[40]; TCHAR szInUse[40]; char mask, *current; HWND portHwnd; DEVINST devInst,newInst; //DbgOut(TEXT("FillStartComCb\n")); portHwnd = GetDlgItem(ParentHwnd, PP_START_COM); if (Params->hComDB == HCOMDB_INVALID_HANDLE_VALUE) { // This happens if we don't have sufficient security privileges. EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } if (Params->PortUsage == NULL || Params->PortUsageSize == 0) { MyMessageBox(ParentHwnd, IDS_MEM_ALLOC_WRN, IDS_CYCLOMY, MB_ICONWARNING); EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } if (!LoadString(g_hInst, IDS_IN_USE, szInUse, CharSizeOf(szInUse))) { wcscpy(szInUse, _T(" (in use)")); } // // first tally up which ports NOT to offer in list box, ie, // my ports should not appear as In Use. // if (CM_Get_Child(&devInst,(Params->DeviceInfoData)->DevInst,0) == CR_SUCCESS) { if ((dwError=GetPortName(devInst,Params->szComName,sizeof(Params->szComName))) != ERROR_SUCCESS) { MyMessageBoxWithErr(ParentHwnd,IDS_START_COM_DISABLED,IDS_CYCLOMY,MB_ICONWARNING,dwError); EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } nCurPortNum = myatoi(&Params->szComName[3]); //nCom = myatoi(&szCom[3]); if ((dwError=CheckComRange(ParentHwnd,Params,nCurPortNum)) != COM_RANGE_OK) { if (dwError == COM_RANGE_TOO_BIG) { MyMessageBox(ParentHwnd,IDS_COM_TOO_BIG_WRN,IDS_CYCLOMY,MB_ICONWARNING); } else { MyMessageBox(ParentHwnd,IDS_MEM_ALLOC_WRN,IDS_CYCLOMY,MB_ICONWARNING); } EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } current = Params->PortUsage + (nCurPortNum-1) / 8; if ((i = nCurPortNum % 8)) *current &= ~(1 << (i-1)); else *current &= ~(0x80); Params->NumChildren = 1; while (CM_Get_Sibling(&newInst,devInst,0) == CR_SUCCESS) { if ((dwError=GetPortName(newInst,szCom,sizeof(szCom))) != ERROR_SUCCESS) { MyMessageBoxWithErr(ParentHwnd,IDS_START_COM_DISABLED,IDS_CYCLOMY,MB_ICONWARNING,dwError); EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } nCom = myatoi(&szCom[3]); if ((dwError=CheckComRange(ParentHwnd,Params,nCom)) != COM_RANGE_OK) { if (dwError == COM_RANGE_TOO_BIG) { MyMessageBox(ParentHwnd,IDS_COM_TOO_BIG_WRN,IDS_CYCLOMY,MB_ICONWARNING); } else { MyMessageBox(ParentHwnd,IDS_MEM_ALLOC_WRN,IDS_CYCLOMY,MB_ICONWARNING); } EnableWindow(portHwnd, FALSE); EnableWindow(GetDlgItem(ParentHwnd, IDC_START_COM), FALSE); return 0; } current = Params->PortUsage + (nCom-1) / 8; if ((i = nCom % 8)) *current &= ~(1 << (i-1)); else *current &= ~(0x80); Params->NumChildren++; devInst = newInst; } } // Fill Start COM Combo Box current = Params->PortUsage; mask = 0x1; for(nEntries = j = 0, i = MIN_COM-1; i < MAX_COM_PORT; i++) { wsprintf(szCom, TEXT("COM%d"), i+1); if (*current & mask) { wcscat(szCom, szInUse); } if (mask == (char) 0x80) { mask = 0x01; current++; } else { mask <<= 1; } ComboBox_AddString(portHwnd, szCom); } ComboBox_SetCurSel(portHwnd, nCurPortNum-1); return 1; } /* FillStartComCb */ /*++ Routine Description: SavePortSettingsDlg save changes in the Cyclom-Y Settings dlg sheet Arguments: Params: where to save the data to ParentHwnd: address of the window Return Value: BOOL: FALSE if function fails, TRUE if function passes --*/ BOOL SavePortSettingsDlg( IN HWND DialogHwnd, IN PPORT_PARAMS Params ) { BOOL retValue = TRUE; // // store changes to win.ini; broadcast changes to apps // if (Params->ShowStartCom) { ComDBOpen(&Params->hComDB); retValue = SavePortSettings(DialogHwnd, Params); if (Params->hComDB != HCOMDB_INVALID_HANDLE_VALUE) { ComDBClose(Params->hComDB); } } return retValue; } /* SavePortSettingsDlg */ /*++ Routine Description: SavePortSettings Read the dlg screen selections for baudrate, parity, etc. If changed from what we started with, then save them Arguments: hDlg: address of the window szComName: which comport we're dealing with Params: contains, baudrate, parity, etc Return Value: BOOL: FALSE if function fails, TRUE if function passes --*/ BOOL SavePortSettings( IN HWND DialogHwnd, IN PPORT_PARAMS Params ) { UINT startComNum, curComNum, newComNum = CB_ERR; DEVINST devInst,newInst; TCHAR buffer[BUFFER_SIZE]; PCHILD_DATA ChildPtr,VarChildPtr; DWORD numChild=0; DWORD i; DWORD dwError = ERROR_SUCCESS; BOOL retValue = FALSE; // FALSE = failure //DbgOut(TEXT("SavePortSettings\n")); curComNum = myatoi(Params->szComName + wcslen(m_szCOM)); newComNum = ComboBox_GetCurSel(GetDlgItem(DialogHwnd, PP_START_COM)); if (newComNum == CB_ERR) { newComNum = curComNum; } else { newComNum++; } if (newComNum == curComNum) { return TRUE; // No change, so just accept it. } startComNum = newComNum; if (Params->hComDB == HCOMDB_INVALID_HANDLE_VALUE) { MyMessageBox(DialogHwnd,IDS_INVALID_HCOMDB,IDS_CYCLOMY,MB_ICONERROR); return retValue; } ChildPtr = (PCHILD_DATA) LocalAlloc(LPTR,Params->NumChildren * sizeof(CHILD_DATA)); if (ChildPtr == NULL) { MyMessageBox(DialogHwnd, IDS_MEM_ALLOC_ERR, IDS_CYCLOMY, MB_ICONERROR); return retValue; } VarChildPtr = ChildPtr; if (CM_Get_Child(&devInst,(Params->DeviceInfoData)->DevInst,0) == CR_SUCCESS) { if ((dwError = GetPortData(devInst,VarChildPtr)) != ERROR_SUCCESS) { MyMessageBoxWithErr(DialogHwnd,IDS_START_COM_NOT_CHANGED,IDS_CYCLOMY, MB_ICONERROR,dwError); //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } numChild++; if (!QueryDosDevice(VarChildPtr->szComName, buffer, BUFFER_SIZE-1)) { dwError = GetLastError(); MyMessageBoxWithErr(DialogHwnd, IDS_START_COM_NOT_CHANGED, IDS_CYCLOMY, MB_ICONERROR,dwError); //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } //#if DBG //{ //TCHAR buf[500]; //wsprintf(buf, TEXT("QueryDosDevice(%s,buffer,%d) returned %s\n"),VarChildPtr->szComName,BUFFER_SIZE-1,buffer); //DbgOut(buf); //} //#endif if (TryToOpen(VarChildPtr->szComName) == FALSE) { dwError = GetLastError(); MyMessageBox(DialogHwnd, IDS_PORT_OPEN_ERROR,IDS_CYCLOMY,MB_ICONERROR, VarChildPtr->szComName); //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } if ((dwError = CheckComRange(DialogHwnd,Params,newComNum)) != COM_RANGE_OK) { if (dwError == COM_RANGE_TOO_BIG) { MyMessageBox(DialogHwnd, IDS_COM_TOO_BIG_ERR,IDS_CYCLOMY,MB_ICONERROR); } else { MyMessageBox(DialogHwnd, IDS_MEM_ALLOC_ERR,IDS_CYCLOMY,MB_ICONERROR); } //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } if (!NewComAvailable(Params,newComNum)) { MyMessageBox(DialogHwnd, IDS_PORT_IN_USE_ERROR, IDS_CYCLOMY,MB_ICONERROR); //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } VarChildPtr->NewComNum = newComNum; while (CM_Get_Sibling(&newInst,devInst,0) == CR_SUCCESS) { if (numChild >= Params->NumChildren) { // We should never reach here. DbgOut(TEXT("cyycoins Somehow I'm getting different number of children this time!\n")); break; } VarChildPtr++; if ((dwError=GetPortData(newInst,VarChildPtr)) != ERROR_SUCCESS) { MyMessageBoxWithErr(DialogHwnd, IDS_START_COM_NOT_CHANGED, IDS_CYCLOMY, MB_ICONERROR,dwError); goto Return; } numChild++; if (!QueryDosDevice(VarChildPtr->szComName, buffer, BUFFER_SIZE-1)) { dwError = GetLastError(); MyMessageBoxWithErr(DialogHwnd, IDS_START_COM_NOT_CHANGED, IDS_CYCLOMY, MB_ICONERROR,dwError); goto Return; } if (TryToOpen(VarChildPtr->szComName) == FALSE) { dwError = GetLastError(); MyMessageBox(DialogHwnd, IDS_PORT_OPEN_ERROR,IDS_CYCLOMY, MB_ICONERROR,VarChildPtr->szComName); goto Return; } while (1) { newComNum++; if ((dwError=CheckComRange(DialogHwnd,Params,newComNum)) != COM_RANGE_OK) { if (dwError == COM_RANGE_TOO_BIG) { MyMessageBox(DialogHwnd, IDS_COM_TOO_BIG_ERR,IDS_CYCLOMY,MB_ICONERROR); } else { MyMessageBox(DialogHwnd, IDS_MEM_ALLOC_ERR,IDS_CYCLOMY,MB_ICONERROR); } //ComboBox_SetCurSel(GetDlgItem(DialogHwnd,PP_START_COM), curComNum-1); goto Return; } if (NewComAvailable(Params,newComNum)) { break; } } VarChildPtr->NewComNum = newComNum; devInst = newInst; } } if (startComNum < curComNum) { VarChildPtr = ChildPtr; } for (i=0; iszComName); ushIndex = (ushIndex == CB_ERR) ? 0 : ushIndex; ComboBox_SetCurSel(GetDlgItem(DialogHwnd, PP_START_COM), ushIndex); } void MigratePortSettings( LPCTSTR OldComName, LPCTSTR NewComName ) { TCHAR settings[BUFFER_SIZE]; TCHAR szNew[20], szOld[20]; lstrcpy(szOld, OldComName); wcscat(szOld, m_szColon); lstrcpy(szNew, NewComName); wcscat(szNew, m_szColon); settings[0] = TEXT('\0'); GetProfileString(m_szPorts, szOld, TEXT(""), settings, sizeof(settings) / sizeof(TCHAR) ); // // Insert the new key based on the old one // if (settings[0] == TEXT('\0')) { WriteProfileString(m_szPorts, szNew, m_szDefParams); } else { WriteProfileString(m_szPorts, szNew, settings); } // // Notify everybody of the changes and blow away the old key // SendWinIniChange((LPTSTR)m_szPorts); WriteProfileString(m_szPorts, szOld, NULL); } void EnactComNameChanges( IN HWND ParentHwnd, IN PPORT_PARAMS Params, IN PCHILD_DATA ChildPtr) { DWORD dwNewComNameLen; TCHAR buffer[BUFFER_SIZE]; TCHAR szFriendlyNameFormat[LINE_LEN]; TCHAR szDeviceDesc[LINE_LEN]; TCHAR szNewComName[20]; UINT i; UINT curComNum,NewComNum; SP_DEVINSTALL_PARAMS spDevInstall; //DbgOut(TEXT("EnactComNameChanges\n")); NewComNum = ChildPtr->NewComNum; curComNum = myatoi(ChildPtr->szComName + wcslen(m_szCOM)); wsprintf(szNewComName, _T("COM%d"), NewComNum); dwNewComNameLen = ByteCountOf(wcslen(szNewComName) + 1); // // Change the name in the symbolic namespace. // First try to get what device the old com name mapped to // (ie something like \Device\Serial0). Then remove the mapping. If // the user isn't an admin, then this will fail and the dialog will popup. // Finally, map the new name to the old device retrieved from the // QueryDosDevice // //if (updateMapping) { BOOL removed; HKEY hSerialMap; if (!QueryDosDevice(ChildPtr->szComName, buffer, BUFFER_SIZE-1)) { // // This shouldn't happen because the previous QueryDosDevice call // succeeded // MyMessageBox(ParentHwnd, IDS_PORT_RENAME_ERROR, IDS_CYCLOMY, MB_ICONERROR, curComNum); return; } // // If this fails, then the following define will just replace the current // mapping. // removed = DefineDosDevice(DDD_REMOVE_DEFINITION, ChildPtr->szComName, NULL); if (!DefineDosDevice(DDD_RAW_TARGET_PATH, szNewComName, buffer)) { // // error, first fix up the remove definition and restore the old // mapping // if (removed) { DefineDosDevice(DDD_RAW_TARGET_PATH, ChildPtr->szComName, buffer); } MyMessageBox(ParentHwnd, IDS_PORT_RENAME_ERROR, IDS_CYCLOMY, MB_ICONERROR, curComNum); return; } // // Set the \\HARDWARE\DEVICEMAP\SERIALCOMM field // if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_szRegSerialMap, 0, KEY_ALL_ACCESS, &hSerialMap) == ERROR_SUCCESS) { TCHAR szSerial[BUFFER_SIZE]; DWORD dwSerialSize, dwEnum, dwType, dwComSize; TCHAR szCom[BUFFER_SIZE]; i = 0; do { dwSerialSize = CharSizeOf(szSerial); dwComSize = sizeof(szCom); dwEnum = RegEnumValue(hSerialMap, i++, szSerial, &dwSerialSize, NULL, &dwType, (LPBYTE)szCom, &dwComSize); if (dwEnum == ERROR_SUCCESS) { if(dwType != REG_SZ) continue; if (wcscmp(szCom, ChildPtr->szComName) == 0) { RegSetValueEx(hSerialMap, szSerial, 0, REG_SZ, (PBYTE) szNewComName, dwNewComNameLen); break; } } } while (dwEnum == ERROR_SUCCESS); } RegCloseKey(hSerialMap); } // // Update the com db // if (Params->hComDB != HCOMDB_INVALID_HANDLE_VALUE) { ComDBReleasePort(Params->hComDB, (DWORD) curComNum); ComDBClaimPort(Params->hComDB, (DWORD) NewComNum, TRUE, NULL); } // // Set the friendly name in the form of DeviceDesc (COM#) // if (ReplaceFriendlyName(ChildPtr->DeviceInfoSet, &ChildPtr->DeviceInfoData, szNewComName) == FALSE) { // ReplaceFriendlyName failed. Use original code. if (LoadString(g_hInst, IDS_FRIENDLY_FORMAT, szFriendlyNameFormat, CharSizeOf(szFriendlyNameFormat)) && SetupDiGetDeviceRegistryProperty(ChildPtr->DeviceInfoSet, &ChildPtr->DeviceInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE) szDeviceDesc, sizeof(szDeviceDesc), NULL)) { wsprintf(buffer, szFriendlyNameFormat, szDeviceDesc, szNewComName); } else { // // Use the COM port name straight out // lstrcpy(buffer, szNewComName); } SetupDiSetDeviceRegistryProperty(ChildPtr->DeviceInfoSet, &ChildPtr->DeviceInfoData, SPDRP_FRIENDLYNAME, (PBYTE) buffer, ByteCountOf(wcslen(buffer)+1)); } // // Set the parent dialog's title to reflect the change in the com port's name // //ChangeParentTitle(GetParent(ParentHwnd), AdvancedData->szComName, szNewComName); MigratePortSettings(ChildPtr->szComName, szNewComName); // // Update the PortName value in the devnode // RegSetValueEx(ChildPtr->hDeviceKey, m_szPortName, 0, REG_SZ, (PBYTE)szNewComName, dwNewComNameLen); // // Now broadcast this change to the device manager // ZeroMemory(&spDevInstall, sizeof(SP_DEVINSTALL_PARAMS)); spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(Params->DeviceInfoSet, Params->DeviceInfoData, &spDevInstall)) { spDevInstall.Flags |= DI_PROPERTIES_CHANGE; SetupDiSetDeviceInstallParams(Params->DeviceInfoSet, Params->DeviceInfoData, &spDevInstall); } } BOOL NewComAvailable( IN PPORT_PARAMS Params, IN DWORD NewComNum ) { DWORD i; UCHAR mask; if ((i = NewComNum % 8)) mask = 1 << (i-1); else mask = (char) 0x80; if (Params->PortUsage[(NewComNum-1)/8] & mask) { // // Port has been previously claimed // return FALSE; } return TRUE; } BOOL TryToOpen( IN PTCHAR szCom ) { TCHAR szComFileName[20]; // more than enough for "\\.\COMXxxx" HANDLE hCom; lstrcpy(szComFileName, L"\\\\.\\"); lstrcat(szComFileName, szCom); // // Make sure that the port has not been opened by another application // hCom = CreateFile(szComFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // // If the file handle is invalid, then the com port is open, warn the user // if (hCom == INVALID_HANDLE_VALUE) { return FALSE; } CloseHandle(hCom); return TRUE; } ULONG GetPortName( IN DEVINST PortInst, IN OUT TCHAR *ComName, IN ULONG ComNameSize ) { HDEVINFO portInfo; SP_DEVINFO_DATA portData; TCHAR portId[MAX_DEVICE_ID_LEN]; DWORD dwPortNameSize, dwError; HKEY hDeviceKey; dwError = ERROR_SUCCESS; if (CM_Get_Device_ID(PortInst,portId,CharSizeOf(portId),0) == CR_SUCCESS) { portInfo = SetupDiCreateDeviceInfoList(NULL,NULL); if (portInfo != INVALID_HANDLE_VALUE) { portData.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiOpenDeviceInfo(portInfo,portId,NULL,0,&portData)) { hDeviceKey = SetupDiOpenDevRegKey(portInfo,&portData, DICS_FLAG_GLOBAL,0, DIREG_DEV,KEY_READ); if (hDeviceKey == INVALID_HANDLE_VALUE) { dwError = GetLastError(); } dwPortNameSize = ComNameSize; dwError = RegQueryValueEx(hDeviceKey, m_szPortName, // "PortName" NULL, NULL, (PBYTE)ComName, &dwPortNameSize); if (dwError == ERROR_SUCCESS) { // #if DBG // { // TCHAR buf[500]; // wsprintf(buf, TEXT("cyycoins PortName %s\n"),ComName); // DbgOut(buf); // } // #endif } RegCloseKey(hDeviceKey); } else { dwError = GetLastError(); } SetupDiDestroyDeviceInfoList(portInfo); } else { dwError = GetLastError(); } } return dwError; } ULONG GetPortData( IN DEVINST PortInst, OUT PCHILD_DATA ChildPtr ) { HDEVINFO portInfo; HKEY hDeviceKey; TCHAR portId[MAX_DEVICE_ID_LEN]; DWORD dwPortNameSize,dwError; dwError = ERROR_SUCCESS; portInfo = INVALID_HANDLE_VALUE; hDeviceKey = INVALID_HANDLE_VALUE; if (CM_Get_Device_ID(PortInst,portId,CharSizeOf(portId),0) == CR_SUCCESS) { portInfo = SetupDiCreateDeviceInfoList(NULL,NULL); if (portInfo != INVALID_HANDLE_VALUE) { ChildPtr->DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (SetupDiOpenDeviceInfo(portInfo, portId, NULL, 0, &ChildPtr->DeviceInfoData)) { hDeviceKey = SetupDiOpenDevRegKey(portInfo,&ChildPtr->DeviceInfoData, DICS_FLAG_GLOBAL,0, DIREG_DEV,KEY_ALL_ACCESS); if (hDeviceKey == INVALID_HANDLE_VALUE) { dwError = GetLastError(); } else { dwPortNameSize = sizeof(ChildPtr->szComName); dwError = RegQueryValueEx(hDeviceKey, m_szPortName, // "PortName" NULL, NULL, (PBYTE)ChildPtr->szComName, &dwPortNameSize); if (dwError != ERROR_SUCCESS) { RegCloseKey(hDeviceKey); hDeviceKey = INVALID_HANDLE_VALUE; } } } else { dwError = GetLastError(); } if (dwError != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(portInfo); portInfo = INVALID_HANDLE_VALUE; } } else { dwError = GetLastError(); } } ChildPtr->DeviceInfoSet = portInfo; ChildPtr->hDeviceKey = hDeviceKey; return dwError; } void ClosePortData( IN PCHILD_DATA ChildPtr ) { if (ChildPtr->hDeviceKey != INVALID_HANDLE_VALUE) { RegCloseKey(ChildPtr->hDeviceKey); } if (ChildPtr->DeviceInfoSet != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(ChildPtr->DeviceInfoSet); } } /*++ Routine Description: CheckComRange Returns TRUE if Com port is in the PortUsage range. Arguments: ParentHwnd: address of the window Params: where to save the data to ComPort: com port to be checked Return Value: COM_RANGE_OK COM_RANGE_TOO_BIG COM_RANGE_MEM_ERR --*/ DWORD CheckComRange( HWND ParentHwnd, PPORT_PARAMS Params, DWORD nCom ) { PBYTE newPortUsage; DWORD portsReported; HCOMDB hComDB; DWORD comUsageSize = Params->PortUsageSize*8; if (nCom > MAX_COM_PORT) { return COM_RANGE_TOO_BIG; } if (nCom > comUsageSize) { if (comUsageSize < 256) { comUsageSize = 256; } else if (comUsageSize < 1024) { comUsageSize = 1024; } else if (comUsageSize < 2048) { comUsageSize = 2048; } else { return COM_RANGE_TOO_BIG; } // Re-alloc to COMDB_MAX_PORTS_ARBITRATED newPortUsage = (PBYTE) LocalAlloc(LPTR,comUsageSize/8); if (newPortUsage == NULL) { return COM_RANGE_MEM_ERR; } else { //DbgOut(TEXT("Params->PortUsage replaced\n")); LocalFree(Params->PortUsage); Params->PortUsage = newPortUsage; Params->PortUsageSize = comUsageSize/8; ComDBGetCurrentPortUsage(Params->hComDB, NULL, 0, 0, &portsReported ); if (comUsageSize > portsReported) { if (ComDBResizeDatabase(Params->hComDB, comUsageSize) != ERROR_SUCCESS){ //return COM_RANGE_TOO_BIG; // TODO: Replace by a better message. } } ComDBGetCurrentPortUsage(Params->hComDB, Params->PortUsage, Params->PortUsageSize, CDB_REPORT_BITS, &portsReported ); } } return COM_RANGE_OK; }