/*++ BUILD Version: 0000 // Increment this if a change has global effects Copyright (c) 1995 Microsoft Corporation Module Name: kmesp.c Abstract: This module contains Author: Dan Knudson (DanKn) 12-Apr-1995 Revision History: Notes: --*/ #include "windows.h" #include "winioctl.h" #include "stdio.h" #include "stdarg.h" #include "string.h" #include "ndistapi.h" #include "kmesp.h" #include "resource.h" #include "..\sys\intrface.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ghInst = hInstance; DialogBox( ghInst, (LPCSTR) MAKEINTRESOURCE(IDD_DIALOG1), (HWND) NULL, (DLGPROC) MainWndProc ); return 0; } void DoRequestUI( PREQUEST_PARAMS pRequestParams ) { LONG i, count = SendMessage (ghwndList1, LB_GETCOUNT, 0, 0); char buf[64]; switch (pRequestParams->Oid) { case OID_TAPI_CLOSE: { char szLineName[8]; sprintf (szLineName, "Line%d", pRequestParams->hWidget); for (i = 0; i < count; i++) { SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf); if (strstr (buf, szLineName)) { break; } } sprintf (buf, "%s (closed)", szLineName); SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0); SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf); break; } case OID_TAPI_CLOSE_CALL: { char szhdCall[16]; sprintf (szhdCall, "x%x", pRequestParams->hWidget); for (i = 0; i < count; i++) { SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf); if (strstr (buf, szhdCall)) { break; } } SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0); break; } case OID_TAPI_MAKE_CALL: { if (pRequestParams->Status == NDIS_STATUS_SUCCESS) { char szLineName[8]; sprintf (szLineName, "Line%d", pRequestParams->hWidget); for (i = 0; i < count; i++) { SendMessage (ghwndList1, LB_GETTEXT, (WPARAM) i, (LPARAM) buf); if (strstr (buf, szLineName)) { break; } } i++; sprintf (buf, " hdCall = x%x", pRequestParams->ulRequestSpecific); SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf); } } case OID_TAPI_OPEN: { if (pRequestParams->Status == NDIS_STATUS_SUCCESS) { PMYWIDGET pWidget; for (i = 0; i < count; i++) { pWidget = (PMYWIDGET) SendMessage( ghwndList1, LB_GETITEMDATA, (WPARAM) i, 0 ); if (pWidget->LineID == pRequestParams->hWidget) { break; } } sprintf (buf, "%s (open)", szLineName); SendMessage (ghwndList1, LB_DELETESTRING, (WPARAM) i, 0); SendMessage (ghwndList1, LB_INSERTSTRING, (WPARAM) i, (LPARAM) buf); } break; } case OID_TAPI_PROVIDER_INITIALIZE: { if (pRequestParams->Status == NDIS_STATUS_SUCCESS) { for (i = 0; i < pRequestParams->ulRequestSpecific; i++) { PMYWIDGET pWidget = MyAlloc (sizeod(MYWIDGET)); pWidget->LineID = pRequestParams->hWidget + i; sprintf (buf, "Line%d (closed)", pRequestParams->hWidget + i); SendMessage (ghwndList1, LB_ADDSTRING, 0, (LPARAM) buf); SendMessage (ghwndList1, LB_SETITEMDATA, i, (LPARAM) pWidget); } } break; } case OID_TAPI_PROVIDER_SHUTDOWN: { while ((pWidget = SendMessage (ghwndList1, LB_GETITEMDATA, 0, 0)) != LB_ERR) { MyFree (pWidget); SendMessage (ghwndList1, LB_DELETESTRING, 0, 0); } break; } default: break; } } BOOL CALLBACK MainWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { static HICON hIcon; static int icyButton, icyBorder; static BOOL bCaptured = FALSE; static LONG xCapture, cxVScroll; static int cyWnd; static HFONT hFont; switch (msg) { case WM_INITDIALOG: { char buf[64]; RECT rect; // // Init some globals // #ifdef WIN32 // ghShowStrBufMutex = CreateMutex( // NULL, // no security attrs // FALSE, // unowned // NULL // unnamed // ); #endif hIcon = LoadIcon (ghInst, MAKEINTRESOURCE(IDI_ICON1)); ghwndMain = hwnd; ghwndList1 = GetDlgItem (hwnd, IDC_LIST1); ghwndList2 = GetDlgItem (hwnd, IDC_LIST2); ghwndEdit = GetDlgItem (hwnd, IDC_EDIT1); ghMenu = GetMenu (hwnd); icyBorder = GetSystemMetrics (SM_CYFRAME); GetWindowRect (GetDlgItem (hwnd, IDC_BUTTON1), &rect); icyButton = (rect.bottom - rect.top) + icyBorder + 3; cxVScroll = 2*GetSystemMetrics (SM_CXVSCROLL); // // Get ini file settings // gbManualResults = FALSE; gdwCompletionMode = (DWORD) GetProfileInt( szMySection, "CompletionMode", 1 ); PostMessage (hwnd, WM_COMMAND, IDM_SYNCCOMPL + gdwCompletionMode, 0); // // Set control fonts // { HWND hwndCtrl = GetDlgItem (hwnd, IDC_BUTTON1); hFont = CreateFont( 13, 5, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 34, "MS Sans Serif" ); do { SendMessage( hwndCtrl, WM_SETFONT, (WPARAM) hFont, 0 ); } while ((hwndCtrl = GetNextWindow (hwndCtrl, GW_HWNDNEXT))); } // // Read in control size ratios // cxWnd = GetProfileInt (szMySection, "cxWnd", 100); cxList1 = GetProfileInt (szMySection, "cxList1", 25); // // Send self WM_SIZE to position child controls correctly // GetProfileString( szMySection, "Left", "0", buf, 63 ); if (strcmp (buf, "max") == 0) { ShowWindow (hwnd, SW_SHOWMAXIMIZED); } else if (strcmp (buf, "min") == 0) { ShowWindow (hwnd, SW_SHOWMINIMIZED); } else { int left, top, right, bottom; int cxScreen = GetSystemMetrics (SM_CXSCREEN); int cyScreen = GetSystemMetrics (SM_CYSCREEN); left = GetProfileInt (szMySection, "Left", 0); top = GetProfileInt (szMySection, "Top", 3*cyScreen/4); right = GetProfileInt (szMySection, "Right", cxScreen); bottom = GetProfileInt (szMySection, "Bottom", cyScreen); SetWindowPos( hwnd, HWND_TOP, left, top, right - left, bottom - top, SWP_SHOWWINDOW ); GetClientRect (hwnd, &rect); SendMessage( hwnd, WM_SIZE, 0, MAKELONG((rect.right-rect.left),(rect.bottom-rect.top)) ); ShowWindow (hwnd, SW_SHOW); } if ((ghDriver = CreateFile( "\\\\.\\STUBMP", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL )) == INVALID_HANDLE_VALUE) { ShowStr ( "Error opening stubmp driver, lastErr=%ld", GetLastError() ); } else { DWORD dwThreadID; ShowStr ("Stubmp driver opened"); ghThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) EventsThread, NULL, 0, &dwThreadID ); } break; } case WM_COMMAND: switch (LOWORD((DWORD)wParam)) { case IDM_REGISTER: { DWORD params = RT_REGISTER; DevIoCtl (¶ms, sizeof(DWORD)); ShowStr ("Stubmp driver registered with connection wrapper"); break; } case IDM_DEREGISTER: { DWORD params = RT_DEREGISTER; DevIoCtl (¶ms, sizeof(DWORD)); ShowStr ("Stubmp driver deregistered from connection wrapper"); break; } case IDM_SYNCCOMPL: case IDM_ASYNCCOMPL: case IDM_MANUALCOMPL: gdwCompletionMode = LOWORD((DWORD)wParam) - IDM_SYNCCOMPL; CheckMenuItem( ghMenu, IDM_SYNCCOMPL, MF_BYCOMMAND | (gdwCompletionMode == SYNC_COMPLETIONS ? MF_CHECKED : MF_UNCHECKED) ); CheckMenuItem( ghMenu, IDM_ASYNCCOMPL, MF_BYCOMMAND | (gdwCompletionMode == ASYNC_COMPLETIONS ? MF_CHECKED : MF_UNCHECKED) ); CheckMenuItem( ghMenu, IDM_MANUALCOMPL, MF_BYCOMMAND | (gdwCompletionMode == MANUAL_COMPLETIONS ? MF_CHECKED : MF_UNCHECKED) ); break; case IDM_MANUALRESULTS: gbManualResults = (gbManualResults ? FALSE : TRUE); CheckMenuItem( ghMenu, IDM_MANUALRESULTS, MF_BYCOMMAND | (gbManualResults ? MF_CHECKED : MF_UNCHECKED) ); break; case IDM_EXIT: PostMessage (hwnd, WM_CLOSE, 0, 0); break; case IDM_ABOUT: DialogBox( ghInst, (LPCSTR) MAKEINTRESOURCE(IDD_DIALOG2), hwnd, (DLGPROC) AboutDlgProc ); break; case IDC_LIST2: if (HIWORD(wParam) == LBN_DBLCLK) { LONG lSel = SendMessage (ghwndList2, LB_GETCURSEL, 0, 0); ULONG args[3]; PREQUEST_PARAMS pRequestParams; pRequestParams = (PREQUEST_PARAMS) SendMessage( ghwndList2, LB_GETITEMDATA, (WPARAM) lSel, 0 ); args[0] = RT_COMPLETEREQUEST; args[1] = pRequestParams->pNdisRequest; args[2] = pRequestParams->Status; if (gbManualResults) { char szDlgTitle[] = "Request result"; PARAM_INFO params[] = { { "Status", PT_ORDINAL, pRequestParams->Status, aStatus } }; PARAM_INFO_HEADER paramsHeader = { 1, szDlgTitle, 0, params }; if (DialogBoxParam( ghInst, (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3), (HWND) ghwndMain, (DLGPROC) ParamsDlgProc, (LPARAM) ¶msHeader ) != IDOK) { break; } args[2] = pRequestParams->Status = params[0].dwValue; } DoRequestUI (pRequestParams); DevIoCtl (args, 3 * sizeof(ULONG)); SendMessage (ghwndList2, LB_DELETESTRING, lSel, 0); MyFree (pRequestParams); } break; case IDC_BUTTON1: { LONG sel = SendMessage (ghwndList1, LB_GETCURSEL, 0, 0); if (sel != LB_ERR) { PARAM_INFO params[] = { { "Line", PT_DWORD, 0, NULL }, { "hdCall", PT_DWORD, 0, NULL }, { "dwMsg", PT_ORDINAL, 0, aLineMsgs }, { "dwParam1", PT_DWORD, 0, NULL }, { "dwParam2", PT_DWORD, 0, NULL }, { "dwParam3", PT_DWORD, 0, NULL } }; PARAM_INFO_HEADER paramsHeader = { 6, "Line event", 0, params }; char buf[64]; SendMessage( ghwndList1, LB_GETTEXT, (WPARAM) sel, (LPARAM) buf ); if (strstr (buf, "Line")) { } if (DialogBoxParam( ghInst, (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3), (HWND) hwnd, (DLGPROC) ParamsDlgProc, (LPARAM) ¶msHeader ) == IDOK) { } } break; } case IDC_BUTTON2: MessageBox (hwnd, "new call", "xxx", MB_OK); break; case IDC_BUTTON3: SetWindowText (ghwndEdit, ""); break; } break; case WM_PAINT: { PAINTSTRUCT ps; BeginPaint (hwnd, &ps); FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH)); EndPaint (hwnd, &ps); break; } case WM_MOUSEMOVE: { LONG x = (LONG)((short)LOWORD(lParam)); int y = (int)((short)HIWORD(lParam)); int cxList1New; if (((y > icyButton) && (x > cxList1)) || bCaptured) { SetCursor( LoadCursor ((HINSTANCE) NULL, MAKEINTRESOURCE(IDC_SIZEWE)) ); } if (bCaptured) { x = (x < cxVScroll ? cxVScroll : x); x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x); cxList1New = (int) (cxList1 + x - xCapture); SetWindowPos( ghwndList1, GetNextWindow (ghwndList1, GW_HWNDPREV), 0, icyButton, cxList1New, 2*cyWnd/3, SWP_SHOWWINDOW ); SetWindowPos( ghwndList2, GetNextWindow (ghwndList2, GW_HWNDPREV), 0, icyButton + 2*cyWnd/3 + icyBorder, cxList1New, cyWnd/3 - icyBorder, SWP_SHOWWINDOW ); SetWindowPos( ghwndEdit, GetNextWindow (ghwndEdit, GW_HWNDPREV), (int) cxList1New + icyBorder, icyButton, (int)cxWnd - (cxList1New + icyBorder), cyWnd, SWP_SHOWWINDOW ); } break; } case WM_LBUTTONDOWN: { if (((int)((short)HIWORD(lParam)) > icyButton) && ((int)((short)LOWORD(lParam)) > cxList1)) { xCapture = (LONG)LOWORD(lParam); SetCapture (hwnd); bCaptured = TRUE; } break; } case WM_LBUTTONUP: { if (bCaptured) { POINT p; LONG x; GetCursorPos (&p); MapWindowPoints (HWND_DESKTOP, hwnd, &p, 1); x = (LONG) p.x; ReleaseCapture(); x = (x < cxVScroll ? cxVScroll : x); x = (x > (cxWnd - cxVScroll) ? (cxWnd - cxVScroll) : x); cxList1 = cxList1 + (x - xCapture); bCaptured = FALSE; InvalidateRect (hwnd, NULL, TRUE); } break; } case WM_SIZE: { LONG width = (LONG)LOWORD(lParam); // // Adjust globals based on new size // cxList1 = (cxList1 * width) / cxWnd; cxWnd = width; cyWnd = ((int)HIWORD(lParam)) - icyButton; // // Now reposition the child windows // SetWindowPos( ghwndList1, GetNextWindow (ghwndList1, GW_HWNDPREV), 0, icyButton, (int) cxList1, 2*cyWnd/3, SWP_SHOWWINDOW ); SetWindowPos( ghwndList2, GetNextWindow (ghwndList2, GW_HWNDPREV), 0, icyButton + 2*cyWnd/3 + icyBorder, (int) cxList1, cyWnd/3 - icyBorder, SWP_SHOWWINDOW ); SetWindowPos( ghwndEdit, GetNextWindow (ghwndEdit, GW_HWNDPREV), (int) cxList1 + icyBorder, icyButton, (int)width - ((int)cxList1 + icyBorder), cyWnd, SWP_SHOWWINDOW ); InvalidateRect (hwnd, NULL, TRUE); break; } case WM_CLOSE: SaveIniSettings(); DestroyIcon (hIcon); EndDialog (hwnd, 0); DeleteObject (hFont); CloseHandle (ghDriver); TerminateThread (ghThread, 0); break; } return FALSE; } BOOL CALLBACK AboutDlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch (msg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: EndDialog (hwnd, 0); break; } break; #ifdef WIN32 case WM_CTLCOLORSTATIC: SetBkColor ((HDC) wParam, RGB (192,192,192)); return (BOOL) GetStockObject (LTGRAY_BRUSH); #else case WM_CTLCOLOR: { if (HIWORD(lParam) == CTLCOLOR_STATIC) { SetBkColor ((HDC) wParam, RGB (192,192,192)); return (BOOL) GetStockObject (LTGRAY_BRUSH); } break; } #endif case WM_PAINT: { PAINTSTRUCT ps; BeginPaint (hwnd, &ps); FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH)); EndPaint (hwnd, &ps); break; } } return FALSE; } void ShowStr( LPCSTR format, ... ) { char buf[256]; va_list ap; va_start(ap, format); vsprintf (buf, format, ap ); strcat (buf, "\r\n"); SendMessage (ghwndEdit, EM_SETSEL, (WPARAM)0x7fffffe, (LPARAM)0x7ffffff); SendMessage (ghwndEdit, EM_REPLACESEL, 0, (LPARAM) buf); va_end(ap); } LPVOID MyAlloc( DWORD dwSize ) { return (LocalAlloc (LPTR, dwSize)); } void MyFree( LPVOID p ) { LocalFree (p); } void DevIoCtl( LPVOID pData, DWORD dwSize ) { if (ghDriver != INVALID_HANDLE_VALUE) { DWORD cbReturned; DeviceIoControl ( ghDriver, (DWORD) IOCTL_STUBMP_APPREQUEST, pData, dwSize, NULL, 0, &cbReturned, 0 ); } } void SaveIniSettings( void ) { char buf[32]; RECT rect; GetWindowRect (ghwndMain, &rect); { typedef struct _SAVE_VALUE { char *lpszVal; DWORD dwValue; } SAVE_VALUE, *PSAVE_VALUE; SAVE_VALUE aValues[] = { { "CompletionMode", gdwCompletionMode }, { "Left", (DWORD) rect.left }, { "Top", (DWORD) rect.top }, { "Right", (DWORD) rect.right }, { "Bottom", (DWORD) rect.bottom }, { "cxWnd", (DWORD) cxWnd }, { "cxList1", (DWORD) cxList1 }, { NULL, 0 } }; int i; for (i = 0; aValues[i].lpszVal; i++) { wsprintf (buf, "%ld", aValues[i].dwValue); // decimal WriteProfileString( szMySection, aValues[i].lpszVal, (LPCSTR) buf ); } if (IsIconic (ghwndMain)) { WriteProfileString( szMySection, "Left", "min" ); } else if (IsZoomed (ghwndMain)) { WriteProfileString( szMySection, "Left", "max" ); } } } void EventsThread( LPVOID p ) { ULONG *pFullBuf, *pEmptyBuf, *pBuf1, *pBuf2; DWORD dwBufSize = 1024; OVERLAPPED overlapped; pFullBuf = pBuf1 = LocalAlloc (LPTR, dwBufSize); pEmptyBuf = pBuf2 = LocalAlloc (LPTR, dwBufSize); *pFullBuf = 0; overlapped.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); while (1) { DWORD cbReturned, dwNumBytes; *pEmptyBuf = dwBufSize; DeviceIoControl ( ghDriver, (DWORD) IOCTL_STUBMP_GETEVENTS, pEmptyBuf, dwBufSize, pEmptyBuf, dwBufSize, &cbReturned, &overlapped ); dwNumBytes = *pFullBuf; pFullBuf++; while (dwNumBytes) { switch (*pFullBuf) { case ET_REQUEST: { // // Stubmp received request, show it // static char *pszLookup[] = { "Accept: hdCall=x%x", "Answer: hdCall=x%x", "Close: hdLine=x%x", "CloseCall: hdCall=x%x", "ConditionalMediaDetection: ", "ConfigDialog: DeviceID=x%lx", "DevSpecific: hdLine=x%lx", "Dial: hdCall=x%lx", "Drop: hdCall=x%lx", "GetAddressCaps: DeviceID=x%lx", "GetAddressID: hdLine=x%lx", "GetAddressStatus: hdline=x%lx", "GetCallAddressID: hdCall=x%lx", "GetCallInfo: hdCall=x%lx", "GetCallStatus: hdCall=x%lx", "GetDevCaps: DeviceID=x%lx", "GetDevConfig: DeviceID=x%lx", "GetExtensionID: DeviceID=x%lx", "GetID: hXxx=x%lx", "GetLineDevStatus: hdLine=x%lx", "MakeCall: hdLine=x%lx", "NegotiateExtVersion: DeviceID=x%lx", "Open: DeviceID=x%lx", "Initialize: DeviceIDBase=x%lx", "Shutdown", "SecureCall: hdCall=x%lx", "SelectExtVersion: hdLine=x%lx", "SendUserUserInfo: hdCall=x%lx", "SetAppSpecific: hdCall=x%lx", "SetCallParams: hdCall=x%lx", "SetDefaultMediaDetection: hdLine=x%lx", "SetDevConfig: DeviceID=x%lx", "SetMediaMode: hdCall=x%lx", "SetStatusMessages: hdLine=x%lx" }; PREQUEST_PARAMS pRequestParams = (PREQUEST_PARAMS) pFullBuf; ShowStr( pszLookup[pRequestParams->Oid - OID_TAPI_ACCEPT], pRequestParams->hWidget ); if (pRequestParams->bNeedsCompleting) { PREQUEST_PARAMS pRequestParamsSav; if ((gdwCompletionMode == MANUAL_COMPLETIONS) && (pRequestParamsSav = MyAlloc (sizeof(REQUEST_PARAMS)))) { char buf[128]; int i; LONG index; sprintf( buf, "pReq=x%x: ", pRequestParams->pNdisRequest ); i = strlen (buf); sprintf( buf + i, pszLookup[pRequestParams->Oid - OID_TAPI_ACCEPT], pRequestParams->hWidget ); index = SendMessage( ghwndList2, LB_ADDSTRING, 0, (LPARAM) buf ); memcpy( pRequestParamsSav, pRequestParams, sizeof(REQUEST_PARAMS) ); SendMessage( ghwndList2, LB_SETITEMDATA, (WPARAM) index, (LPARAM) pRequestParamsSav ); } else { ULONG args[3] = { RT_COMPLETEREQUEST, pRequestParams->pNdisRequest, pRequestParams->Status }; if (gbManualResults) { char szDlgTitle[] = "Request result"; PARAM_INFO params[] = { { "Status", PT_ORDINAL, args[2], aStatus } }; PARAM_INFO_HEADER paramsHeader = { 1, szDlgTitle, 0, params }; if (DialogBoxParam( ghInst, (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3), (HWND) ghwndMain, (DLGPROC) ParamsDlgProc, (LPARAM) ¶msHeader ) == IDOK) { args[2] = pRequestParams->Status = params[0].dwValue; } } DoRequestUI (pRequestParams); DevIoCtl (args, 3 * sizeof(ULONG)); } } else { DoRequestUI (pRequestParams); } pFullBuf += (sizeof(REQUEST_PARAMS) / sizeof(ULONG)); dwNumBytes -= sizeof(REQUEST_PARAMS); break; } } // switch } WaitForSingleObject (overlapped.hEvent, INFINITE); pFullBuf = pEmptyBuf; pEmptyBuf = (pFullBuf == pBuf1 ? pBuf2 : pBuf1); } CloseHandle (overlapped.hEvent); ExitThread (0); } BOOL CALLBACK ParamsDlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { DWORD i; typedef struct _DLG_INST_DATA { PPARAM_INFO_HEADER pParamsHeader; LONG lLastSel; char szComboText[MAX_STRING_PARAM_SIZE]; HGLOBAL hComboDS; LPVOID pComboSeg; HWND hwndCombo; } DLG_INST_DATA, *PDLG_INST_DATA; PDLG_INST_DATA pDlgInstData = (PDLG_INST_DATA) GetWindowLong (hwnd, DWL_USER); switch (msg) { case WM_INITDIALOG: { // // Alloc a dlg instance data struct, init it, & save a ptr to it // pDlgInstData = (PDLG_INST_DATA) MyAlloc (sizeof(DLG_INST_DATA)); // BUGBUG if (!pDlgInstData) pDlgInstData->pParamsHeader = (PPARAM_INFO_HEADER) lParam; pDlgInstData->lLastSel = -1; SetWindowLong (hwnd, DWL_USER, (LONG) pDlgInstData); // // Limit the max text length for the combobox's edit field // (NOTE: A combobox ctrl actually has two child windows: a // edit ctrl & a listbox. We need to get the hwnd of the // child edit ctrl & send it the LIMITTEXT msg.) // { HWND hwndChild = GetWindow (pDlgInstData->hwndCombo, GW_CHILD); while (hwndChild) { char buf[8]; GetClassName (hwndChild, buf, 7); if (_stricmp (buf, "edit") == 0) { break; } hwndChild = GetWindow (hwndChild, GW_HWNDNEXT); } SendMessage( hwndChild, EM_LIMITTEXT, (WPARAM) MAX_STRING_PARAM_SIZE - 1, 0 ); } // // Misc other init // pDlgInstData->pParamsHeader = (PPARAM_INFO_HEADER) lParam; SetWindowText (hwnd, pDlgInstData->pParamsHeader->pszDlgTitle); for (i = 0; i < pDlgInstData->pParamsHeader->dwNumParams; i++) { SendDlgItemMessage( hwnd, IDC_LIST1, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pDlgInstData->pParamsHeader->aParams[i].szName ); } break; } case WM_COMMAND: { LONG lLastSel = pDlgInstData->lLastSel; char far *lpszComboText = pDlgInstData->szComboText; PPARAM_INFO_HEADER pParamsHeader = pDlgInstData->pParamsHeader; switch (LOWORD(wParam)) { case IDOK: if (lLastSel != -1) { char buf[MAX_STRING_PARAM_SIZE]; // // Save val of currently selected param // i = GetDlgItemText (hwnd, IDC_COMBO1, buf, MAX_STRING_PARAM_SIZE-1); switch (pParamsHeader->aParams[lLastSel].dwType) { case PT_STRING: { LONG lComboSel; lComboSel = SendDlgItemMessage( hwnd, IDC_COMBO1, CB_GETCURSEL, 0, 0 ); if (lComboSel == 0) // "NULL string (dwXxxSize = 0)" { pParamsHeader->aParams[lLastSel].dwValue = (DWORD) 0; } else // "Valid string" { strncpy( pParamsHeader->aParams[lLastSel].u.buf, buf, MAX_STRING_PARAM_SIZE - 1 ); pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE-1] = 0; pParamsHeader->aParams[lLastSel].dwValue = (DWORD) pParamsHeader->aParams[lLastSel].u.buf; } break; } case PT_DWORD: case PT_FLAGS: case PT_ORDINAL: { if (!sscanf( buf, "%08lx", &pParamsHeader->aParams[lLastSel].dwValue )) { // // Default to 0 // pParamsHeader->aParams[lLastSel].dwValue = 0; } break; } } // switch } // Drop thru to IDCANCEL cleanup code case IDCANCEL: MyFree (pDlgInstData); EndDialog (hwnd, (int)LOWORD(wParam)); break; case IDC_LIST1: if (HIWORD(wParam) == LBN_SELCHANGE) { char buf[MAX_STRING_PARAM_SIZE] = ""; LPCSTR lpstr = buf; LONG lSel = SendDlgItemMessage (hwnd, IDC_LIST1, LB_GETCURSEL, 0, 0); if (lLastSel != -1) { // // Save the old param value // i = GetDlgItemText( hwnd, IDC_COMBO1, buf, MAX_STRING_PARAM_SIZE - 1 ); switch (pParamsHeader->aParams[lLastSel].dwType) { case PT_STRING: { LONG lComboSel; lComboSel = SendDlgItemMessage( hwnd, IDC_COMBO1, CB_GETCURSEL, 0, 0 ); if (lComboSel == 0) // "NULL string (dwXxxSize = 0)" { pParamsHeader->aParams[lLastSel].dwValue = (DWORD)0; } else // "Valid string" or no sel { strncpy( pParamsHeader->aParams[lLastSel].u.buf, buf, MAX_STRING_PARAM_SIZE - 1 ); pParamsHeader->aParams[lLastSel].u.buf[MAX_STRING_PARAM_SIZE - 1] = 0; pParamsHeader->aParams[lLastSel].dwValue = (DWORD) pParamsHeader->aParams[lLastSel].u.buf; } break; } case PT_DWORD: case PT_FLAGS: case PT_ORDINAL: { if (!sscanf( buf, "%08lx", &pParamsHeader->aParams[lLastSel].dwValue )) { // // Default to 0 // pParamsHeader->aParams[lLastSel].dwValue = 0; } break; } } // switch } SendDlgItemMessage (hwnd, IDC_LIST2, LB_RESETCONTENT, 0, 0); SendDlgItemMessage (hwnd, IDC_COMBO1, CB_RESETCONTENT, 0, 0); switch (pParamsHeader->aParams[lSel].dwType) { case PT_STRING: { char * aszOptions[] = { "NUL (dwXxxSize=0)", "Valid string" }; for (i = 0; i < 2; i++) { SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) aszOptions[i] ); } if (pParamsHeader->aParams[lSel].dwValue == 0) { i = 0; buf[0] = 0; } else { i = 1; lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue; } SendDlgItemMessage( hwnd, IDC_COMBO1, CB_SETCURSEL, (WPARAM) i, 0 ); break; } case PT_DWORD: { SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (char far *) "0000000" ); if (pParamsHeader->aParams[lSel].u.dwDefValue) { // // Add the default val string to the combo // wsprintf( buf, "%08lx", pParamsHeader->aParams[lSel].u.dwDefValue ); SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) buf ); } SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (char far *) "ffffffff" ); wsprintf( buf, "%08lx", pParamsHeader->aParams[lSel].dwValue ); break; } case PT_ORDINAL: { // // Stick the bit flag strings in the list box // HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2); PLOOKUP pLookup = (PLOOKUP) pParamsHeader->aParams[lSel].u.pLookup; for (i = 0; pLookup[i].dwVal != 0xffffffff; i++) { SendMessage( hwndList2, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pLookup[i].lpszVal ); if (pParamsHeader->aParams[lSel].dwValue == pLookup[i].dwVal) { SendMessage( hwndList2, LB_SETSEL, (WPARAM) TRUE, (LPARAM) MAKELPARAM((WORD)i,0) ); } } SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (char far *) "select none" ); wsprintf( buf, "%08lx", pParamsHeader->aParams[lSel].dwValue ); break; } case PT_FLAGS: { // // Stick the bit flag strings in the list box // HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2); PLOOKUP pLookup = (PLOOKUP) pParamsHeader->aParams[lSel].u.pLookup; for (i = 0; pLookup[i].dwVal != 0xffffffff; i++) { SendMessage( hwndList2, LB_INSERTSTRING, (WPARAM) -1, (LPARAM) pLookup[i].lpszVal ); if (pParamsHeader->aParams[lSel].dwValue & pLookup[i].dwVal) { SendMessage( hwndList2, LB_SETSEL, (WPARAM) TRUE, (LPARAM) MAKELPARAM((WORD)i,0) ); } } SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (char far *) "select none" ); SendDlgItemMessage( hwnd, IDC_COMBO1, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (char far *) "select all" ); wsprintf( buf, "%08lx", pParamsHeader->aParams[lSel].dwValue ); break; } } //switch SetDlgItemText (hwnd, IDC_COMBO1, lpstr); pDlgInstData->lLastSel = lSel; } break; case IDC_LIST2: if (HIWORD(wParam) == LBN_SELCHANGE) { // // BUGBUG in the PT_ORDINAL case we should compare the // currently selected item(s) against the previous DWORD // val and figure out which item we need to deselect, // if any, in order to maintain a mutex of values // PLOOKUP pLookup = (PLOOKUP) pParamsHeader->aParams[lLastSel].u.pLookup; char buf[16]; DWORD dwValue = 0; int far *ai; LONG i, lSelCount = SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0); ai = (int far *) MyAlloc ((size_t)lSelCount * sizeof(int)); SendDlgItemMessage( hwnd, IDC_LIST2, LB_GETSELITEMS, (WPARAM) lSelCount, (LPARAM) ai ); if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS) { for (i = 0; i < lSelCount; i++) { dwValue |= pLookup[ai[i]].dwVal; } } else // if (.dwType == PT_ORDINAL) { if (lSelCount == 1) { dwValue = pLookup[ai[0]].dwVal; } else if (lSelCount == 2) { // // Figure out which item we need to de-select, since // we're doing ordinals & only want 1 item selected // at a time // GetDlgItemText (hwnd, IDC_COMBO1, buf, 16); if (sscanf (buf, "%08lx", &dwValue)) { if (pLookup[ai[0]].dwVal == dwValue) { SendDlgItemMessage( hwnd, IDC_LIST2, LB_SETSEL, 0, (LPARAM) ai[0] ); dwValue = pLookup[ai[1]].dwVal; } else { SendDlgItemMessage( hwnd, IDC_LIST2, LB_SETSEL, 0, (LPARAM) ai[1] ); dwValue = pLookup[ai[0]].dwVal; } } else { // BUGBUG de-select items??? dwValue = 0; } } else if (lSelCount > 2) { // // Determine previous selection & de-select all the // latest selections // GetDlgItemText (hwnd, IDC_COMBO1, buf, 16); if (sscanf (buf, "%08lx", &dwValue)) { for (i = 0; i < lSelCount; i++) { if (pLookup[ai[i]].dwVal != dwValue) { SendDlgItemMessage( hwnd, IDC_LIST2, LB_SETSEL, 0, (LPARAM) ai[i] ); } } } else { // BUGBUG de-select items??? dwValue = 0; } } } MyFree (ai); wsprintf (buf, "%08lx", dwValue); SetDlgItemText (hwnd, IDC_COMBO1, buf); } break; case IDC_COMBO1: switch (HIWORD(wParam)) { case CBN_SELCHANGE: { LONG lSel = SendDlgItemMessage (hwnd, IDC_COMBO1, CB_GETCURSEL, 0, 0); switch (pParamsHeader->aParams[lLastSel].dwType) { case PT_ORDINAL: // // The only option here is "select none" // strcpy (lpszComboText, "00000000"); PostMessage (hwnd, WM_USER+55, 0, 0); break; case PT_FLAGS: { BOOL bSelect = (lSel ? TRUE : FALSE); SendDlgItemMessage( hwnd, IDC_LIST2, LB_SETSEL, (WPARAM) bSelect, (LPARAM) -1 ); if (bSelect) { PLOOKUP pLookup = (PLOOKUP) pParamsHeader->aParams[lLastSel].u.pLookup; DWORD dwValue = 0; int far *ai; LONG i, lSelCount = SendDlgItemMessage (hwnd, IDC_LIST2, LB_GETSELCOUNT, 0, 0); ai = (int far *) MyAlloc( (size_t)lSelCount * sizeof(int) ); SendDlgItemMessage( hwnd, IDC_LIST2, LB_GETSELITEMS, (WPARAM) lSelCount, (LPARAM) ai ); for (i = 0; i < lSelCount; i++) { dwValue |= pLookup[ai[i]].dwVal; } MyFree (ai); wsprintf (lpszComboText, "%08lx", dwValue); } else { strcpy (lpszComboText, "00000000"); } PostMessage (hwnd, WM_USER+55, 0, 0); break; } case PT_STRING: if (lSel == 1) { strncpy( lpszComboText, pParamsHeader->aParams[lLastSel].u.buf, MAX_STRING_PARAM_SIZE ); lpszComboText[MAX_STRING_PARAM_SIZE-1] = 0; } else { lpszComboText[0] = 0; } PostMessage (hwnd, WM_USER+55, 0, 0); break; case PT_DWORD: break; } // switch break; } case CBN_EDITCHANGE: { // // If user entered text in the edit field then copy the // text to our buffer // if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING) { char buf[MAX_STRING_PARAM_SIZE]; GetDlgItemText( hwnd, IDC_COMBO1, buf, MAX_STRING_PARAM_SIZE ); strncpy( pParamsHeader->aParams[lLastSel].u.buf, buf, MAX_STRING_PARAM_SIZE ); pParamsHeader->aParams[lLastSel].u.buf [MAX_STRING_PARAM_SIZE-1] = 0; } break; } } // switch } // switch break; } case WM_USER+55: SetDlgItemText (hwnd, IDC_COMBO1, pDlgInstData->szComboText); break; case WM_CTLCOLORSTATIC: SetBkColor ((HDC) wParam, RGB (192,192,192)); return (BOOL) GetStockObject (LTGRAY_BRUSH); case WM_PAINT: { PAINTSTRUCT ps; BeginPaint (hwnd, &ps); FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH)); EndPaint (hwnd, &ps); break; } } return FALSE; }