www.pudn.com > Acd.rar > AcdSmpl.c
////////////////////////////////////////////////////////////////////////////// // // ACDSMPL.C // // Handles all the UI for ACDSample // ////////////////////////////////////////////////////////////////////////////// #include#include #include #include #include #include "resource.h" #include "acdsmpl.h" ////////////////////////////////////////////////////////////////////////////// // PROTOTYPES ////////////////////////////////////////////////////////////////////////////// static BOOL CreateMainWindow (int nCmdShow); static LRESULT CALLBACK MainDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void MySetWindow(HWND, int); void MySaveWindow(HWND); BOOL ResizeWindows(BOOL bSizeBar, DWORD dwBarLocation); HTREEITEM AddItemToTree(HTREEITEM hParent, LPTSTR lpszName, LPARAM lParam, HTREEITEM * phItem); BOOL DoPopupMenu(HTREEITEM hItem, POINT pt); BOOL DeleteLeafAndStruct(HTREEITEM hItem); BOOL CALLBACK ChangeGroupDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK ChangeAgentDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK AddGroupDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK AddAgentDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT DoCommand(WPARAM wParam, LPARAM lParam); void AddGroupsToMenu(HTREEITEM hItem, HMENU hMenu); BOOL CALLBACK GroupAddToListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL CALLBACK AgentAddToListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL BuildLineList(HWND hWnd, DWORD dwDeviceID); BOOL BuildAddressList(HWND hWnd, HWND hParentWnd, DWORD dwDeviceID); BOOL InitializeTapi(); BOOL CleanUp(); BOOL UpdateGroupLeaf(PGROUP pGroup); BOOL DoAgentView(); BOOL DoGroupView(); BOOL ReadInFile(); BOOL WriteToDisk(); ////////////////////////////////////////////////////////////////////////////// // GLOBALS ////////////////////////////////////////////////////////////////////////////// ACDGLOBALS g; TCHAR gszACDSampleKey[] = TEXT("Software\\Microsoft\\ACDSample"); TCHAR gszPlacementValue[] = TEXT("WindowPlacement"); TCHAR gszBarLocation[] = TEXT("BarLocation"); ////////////////////////////////////////////////////////////////////////////// // // WinMain() // ////////////////////////////////////////////////////////////////////////////// int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // initialize global variables g.hInstance = hInstance; g.pAgents = NULL; g.pGroups = NULL; // init tapi stuff if (!InitializeTapi()) { MessageBox(NULL, TEXT("TAPI could not be initialized.\nVerify that") TEXT("your machine has TAPI devices installed"), TEXT("Cannot start ACDSMPL"), MB_OK); } if (!CreateMainWindow(nCmdShow)) { return 0; } // main message loop while (GetMessage(&msg, NULL, 0, 0)) { if (!IsDialogMessage(g.hMainWnd, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return 1; } ///////////////////////////////////////////////////////////////////////////// // // CreateMainWindow() // ////////////////////////////////////////////////////////////////////////////// BOOL CreateMainWindow (int nCmdShow) { // InitCommonControls for TreeView control InitCommonControls(); // Create the main window g.hMainWnd = CreateDialog(g.hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, MainDlgProc); if (g.hMainWnd == NULL) { return FALSE; } // restore default location MySetWindow(g.hMainWnd, nCmdShow); // store global hwnds g.hTreeWnd = GetDlgItem(g.hMainWnd, IDC_TREEWND); g.hLogWnd = GetDlgItem(g.hMainWnd, IDC_EDITWND); if ((g.hTreeWnd == FALSE) || (g.hLogWnd == FALSE)) { return FALSE; } ResizeWindows(FALSE, 0); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // MainDlgProc() // ////////////////////////////////////////////////////////////////////////////// LRESULT CALLBACK MainDlgProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static BOOL bButtonDown = FALSE; switch (uMsg) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: { LRESULT lResult; lResult = DoCommand(wParam, lParam); return lResult; } // button and mousemove messages tracked to move // the bar between the treeview control and the // edit control case WM_LBUTTONDOWN: { bButtonDown = TRUE; SetCapture(hWnd); return 0; } case WM_LBUTTONUP: { bButtonDown = FALSE; ReleaseCapture(); return 0; } case WM_MOUSEMOVE: { if (bButtonDown) { ResizeWindows(TRUE, (DWORD)LOWORD(lParam)); return 1; } break; } case WM_SIZE: { ResizeWindows(FALSE, 0); return 1; } // catch right click in tree view to make // popup menu case WM_NOTIFY: { LPNMHDR pnmhdr; POINT pt; HTREEITEM hItem; TV_HITTESTINFO hittestinfo; RECT rc; pnmhdr = (LPNMHDR)lParam; // make sure it's a right click and it's in the treeview if ((pnmhdr->code != NM_RCLICK) || (pnmhdr->hwndFrom != g.hTreeWnd)) { break; } GetCursorPos(&pt); GetWindowRect(g.hTreeWnd, &rc); hittestinfo.pt.x = pt.x - rc.left; hittestinfo.pt.y = pt.y - rc.top; // hittest to get the tree view item hItem = TreeView_HitTest(g.hTreeWnd, &hittestinfo); // only display a menu if the mouse is actually // over the item (TVHT_ONITEM) if (hItem == NULL || (!(hittestinfo.flags & TVHT_ONITEM)) ) { return TRUE; } // select that item (right clicking will not select // by default TreeView_Select(g.hTreeWnd, hItem, TVGN_CARET); // create the menu DoPopupMenu(hItem, pt); return TRUE; } case WM_CLOSE: // save the current window location WriteToDisk(); CleanUp(); MySaveWindow(hWnd); PostQuitMessage(0); return 1; default: break; } return 0; } //////////////////////////////////////////////////////////////////////////////// // // ResizeWindows - Handles resizing the two child windows of the // main window. If bSizeBar is true, then the sizing is happening // because the user is moving the bar. if bSizeBar is false, the sizing // is happening because of the WM_SIZE or something like that. // //////////////////////////////////////////////////////////////////////////////// BOOL ResizeWindows(BOOL bSizeBar, DWORD dwBarLocation) { RECT rc, rc2; int x; // is the user moving the bar? if (!bSizeBar) { dwBarLocation = g.dwBarLocation; } GetClientRect(g.hMainWnd, &rc); // make sure the bar is in a OK location if (bSizeBar) { if ((LONG)dwBarLocation < GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) return FALSE; if ((LONG)(rc.right - dwBarLocation) < GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) return FALSE; } // save the bar location g.dwBarLocation = dwBarLocation; // get the size of the frame x = GetSystemMetrics(SM_CXFRAME); // move tree windows MoveWindow(g.hTreeWnd, 0, 0, dwBarLocation, rc.bottom, TRUE); // get the size of the window (in case move window failed GetClientRect(g.hTreeWnd, &rc2); // move the edit window with respect to the tree window MoveWindow(g.hLogWnd, rc2.right-rc2.left+x+SIZEBAR, 0, rc.right-(rc2.right-rc2.left)-x-SIZEBAR, rc.bottom, TRUE); return TRUE; } ////////////////////////////////////////////////////////////////////////////// // // MySetWindow - reads in the window placement from registry // and sets the window and bar. // ////////////////////////////////////////////////////////////////////////////// void MySetWindow(HWND hWnd, int nCmdShow) { WINDOWPLACEMENT pwp; HKEY hKey; DWORD dwDataSize; DWORD dwDataType; RECT rc; pwp.length = sizeof(WINDOWPLACEMENT); // open the key and read in the WINDOWPLACEMENT structure RegOpenKeyEx(HKEY_CURRENT_USER, gszACDSampleKey, 0, KEY_ALL_ACCESS, &hKey); dwDataSize = sizeof(pwp); if ( RegQueryValueEx(hKey, gszPlacementValue, 0, &dwDataType, (LPBYTE)&pwp, &dwDataSize) ) { // if it fails, default ShowWindow(g.hMainWnd, nCmdShow); GetWindowRect(g.hMainWnd, &rc); g.dwBarLocation = (rc.right - rc.left) / 2; } else { // if it succeeds, set the window and bar dwDataSize = sizeof(DWORD); if (RegQueryValueEx(hKey, gszBarLocation, 0, &dwDataType, (LPBYTE)&g.dwBarLocation, &dwDataSize)) { g.dwBarLocation = (pwp.rcNormalPosition.right - pwp.rcNormalPosition.left) / 2; } SetWindowPlacement(g.hMainWnd, &pwp); } RegCloseKey( hKey ); } ////////////////////////////////////////////////////////////////////////////// // // MySaveWindow() - save the current window placement and bar // ////////////////////////////////////////////////////////////////////////////// void MySaveWindow(HWND hWnd) { WINDOWPLACEMENT pwp; HKEY hKey; DWORD dwDisposition; pwp.length = sizeof(WINDOWPLACEMENT); // get and save GetWindowPlacement(hWnd, &pwp); RegCreateKeyEx(HKEY_CURRENT_USER, gszACDSampleKey, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, &dwDisposition); RegSetValueEx(hKey, gszPlacementValue, 0, REG_BINARY, (LPBYTE)&pwp, sizeof(WINDOWPLACEMENT)); RegSetValueEx(hKey, gszBarLocation, 0, REG_DWORD, (LPBYTE)&g.dwBarLocation, sizeof(DWORD)); RegCloseKey( hKey ); } ////////////////////////////////////////////////////////////////////////////// // // AddItemToTree // // add a new leaf to the tree // ////////////////////////////////////////////////////////////////////////////// HTREEITEM AddItemToTree(HTREEITEM hParent, LPTSTR lpszName, LPARAM lParam, HTREEITEM * phItem) { TV_ITEM tvi; TV_INSERTSTRUCT tvins; HTREEITEM hti; tvi.mask = TVIF_TEXT | TVIF_PARAM; // Set the text of the item. tvi.pszText = lpszName; tvi.cchTextMax = lstrlen(lpszName) * sizeof(TCHAR); // Save the pointer to the buffer tvi.lParam = lParam; tvins.item = tvi; tvins.hInsertAfter = TVI_SORT; // Set the parent item tvins.hParent = hParent; // Add the item to the tree-view control. hti = (HTREEITEM) SendMessage(g.hTreeWnd, TVM_INSERTITEM, 0, (LPARAM) (LPTV_INSERTSTRUCT) &tvins); // save hitem if (phItem) { *phItem = hti; } // select the item so it has focus TreeView_Select(g.hTreeWnd, hti, TVGN_CARET); return hti; } ////////////////////////////////////////////////////////////////////////////// // // DoPopupMenu(HTREEITEM hItem, // POINT pt) // // hItem - item to create menu for // pt - location of mouse so we can create menu where it is // // creates a popup menu, depending on what kind of item is selected // ////////////////////////////////////////////////////////////////////////////// BOOL DoPopupMenu(HTREEITEM hItem, POINT pt) { HMENU hMenu; TV_ITEM tvi; TCHAR szNewGroup[] = TEXT("&New Group..."); TCHAR szNewAgent[] = TEXT("New &Agent..."); TCHAR szAddAgent[] = TEXT("A&dd Agent..."); TCHAR szGroupProperties[] = TEXT("&Group Properties..."); TCHAR szAgentStatus[] = TEXT("Agent Status..."); TCHAR szAddGroup[] = TEXT("Add Group..."); TCHAR szAgentProperties[] = TEXT("Agent Properties..."); TCHAR szGroupDelete[] = TEXT("Group Delete"); TCHAR szAgentDelete[] = TEXT("Agent Delete"); TCHAR szSignIn[] = TEXT("Agent Sign In"); TCHAR szSignOut[] = TEXT("Agent Sign Out"); // get the selected item g.hTreeItemWithMenu = hItem; // create the menu hMenu = CreatePopupMenu(); // get the lParam, which is a pointer to the item tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = hItem; TreeView_GetItem(g.hTreeWnd, &tvi); if (!tvi.lParam) { return TRUE; } switch (((PGROUP)tvi.lParam)->dwKey) { // root item case GROUPROOTKEY: AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_NEWGROUP, szNewGroup); break; // root item case AGENTROOTKEY: AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_NEWAGENT, szNewAgent); break; // group leaf case GROUPKEY: AppendMenu(hMenu, MF_ENABLED | MF_STRING, (UINT)IDM_GROUPADDTOLIST, szAddAgent); AppendMenu(hMenu, MF_ENABLED | MF_STRING, (UINT)IDM_GROUPAGENTSTATUS, szAgentStatus); AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_GROUPPROPERTIES, szGroupProperties); AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_GROUPDELETE, szGroupDelete); break; // agent leaf case AGENTKEY: AppendMenu(hMenu, MF_ENABLED | MF_STRING, (UINT)IDM_AGENTADDTOLIST, szAddGroup); AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_AGENTPROPERTIES, szAgentProperties); AppendMenu(hMenu, MF_ENABLED | MF_STRING, IDM_AGENTDELETE, szAgentDelete); break; default: break; } // actually show menu TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, 0, g.hMainWnd, NULL); return TRUE; } /////////////////////////////////////////////////////////////////////////////// // // LRESULT DoCommand(WPARAM wParam, LPARAM lParam) // handle WM_COMMAND messages for MainDlgProc // /////////////////////////////////////////////////////////////////////////////// LRESULT DoCommand(WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { // New - create a new tree, so just init // the items and return case ID_FILE_NEW: DoGroupView(); return 1; // Open - read in a file case ID_FILE_OPEN: ReadInFile(); return 1; case ID_FILE_EXIT: // save the current window location WriteToDisk(); CleanUp(); MySaveWindow(g.hMainWnd); PostQuitMessage(0); return 1; // new group case ID_EDIT_ADDGROUP: case IDM_NEWGROUP: DialogBox(g.hInstance, MAKEINTRESOURCE(IDD_ADD), g.hTreeWnd, AddGroupDlgProc); return 1; // new agent case ID_EDIT_ADDAGENT: case IDM_NEWAGENT: DialogBox(g.hInstance, MAKEINTRESOURCE(IDD_ADDAGENT), g.hTreeWnd, AddAgentDlgProc); return 1; // properties case IDM_GROUPPROPERTIES: DialogBox(g.hInstance, MAKEINTRESOURCE(IDD_ADD), g.hMainWnd, ChangeGroupDlgProc); return 1; // properties case IDM_AGENTPROPERTIES: DialogBox(g.hInstance, MAKEINTRESOURCE(IDD_ADDAGENT), g.hMainWnd, ChangeAgentDlgProc); return 1; // delete case IDM_GROUPDELETE: case IDM_AGENTDELETE: { DeleteLeafAndStruct(g.hTreeItemWithMenu); return 1; } // add to list case IDM_GROUPADDTOLIST: DialogBoxParam(g.hInstance, MAKEINTRESOURCE(IDD_ADDTOLIST), g.hMainWnd, GroupAddToListProc, TRUE); return 1; // add to list case IDM_AGENTADDTOLIST: DialogBoxParam(g.hInstance, MAKEINTRESOURCE(IDD_ADDTOLIST), g.hMainWnd, AgentAddToListProc, FALSE); return 1; case ID_VIEW_GROUP: DoGroupView(); return 1; case ID_VIEW_AGENT: DoAgentView(); return 1; default: break; } return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // // AddGroupDlgProc - Window proc for the add agent/group dialog box // ///////////////////////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK AddGroupDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: // set text appropriately SetWindowText(hWnd, TEXT("Add Group")); BuildLineList(GetDlgItem(hWnd, IDC_LINECOMBO), 0); BuildAddressList(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), hWnd, 0); // set focus on first control SetFocus(GetDlgItem(hWnd, IDC_NAME)); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_LINECOMBO: { if (HIWORD(wParam) == CBN_SELENDOK) { // need to redo addresses BuildAddressList(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), hWnd, 0); return 1; } return 0; } case IDOK: { TCHAR szName[128]; PGROUP pGroup; DWORD dwLine, dwAddress; int item; // get info SendDlgItemMessage(hWnd, IDC_NAME, WM_GETTEXT, 128, (LPARAM)szName); item = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETCURSEL, 0, 0); dwLine = (DWORD)SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETITEMDATA, item, 0); dwAddress = (DWORD)SendDlgItemMessage(hWnd, IDC_ADDRESSCOMBO, CB_GETCURSEL, 0, 0); // create a structure pGroup = AddGroup(szName, dwLine, dwAddress); if (!pGroup) { return 1; } if (g.bGroupView) { // add it to the tree AddItemToTree(g.hGroupParent, pGroup->lpszName, (LPARAM)pGroup, &pGroup->hItem); } EndDialog(hWnd, 1); return 1; } case IDCANCEL: { EndDialog(hWnd, 0); return 1; } default: return 0; } } return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////////// // // AddAgentDlgProc - Window proc for the add agent/group dialog box // ///////////////////////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK AddAgentDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: BuildLineList(GetDlgItem(hWnd, IDC_LINECOMBO), 0); // set focus on first control SetFocus(GetDlgItem(hWnd, IDC_NAME)); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { TCHAR szName[128]; TCHAR szNumber[128]; PAGENT pAgent; DWORD dwLine; int item; // get info SendDlgItemMessage(hWnd, IDC_NAME, WM_GETTEXT, 128, (LPARAM)szName); SendDlgItemMessage(hWnd, IDC_DESTADDRESS, WM_GETTEXT, 128, (LPARAM)szNumber); item = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETCURSEL, 0, 0); dwLine = (DWORD)SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETITEMDATA, item, 0); // create a structure pAgent = AddAgent(szName, szNumber, dwLine); if (!pAgent) { return 1; } if (!g.bGroupView) { // add it to the tree AddItemToTree(g.hAgentParent, pAgent->lpszName, (LPARAM)pAgent, &pAgent->hItem); } EndDialog(hWnd, 1); return 1; } case IDCANCEL: { EndDialog(hWnd, 0); return 1; } default: return 0; } } return 0; } ////////////////////////////////////////////////////////////////////////////////// // // ChangeGroupDlgProc - Window proc for the change (properties) dialog box // for agents/groups // ////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK ChangeGroupDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static TV_ITEM tvi; switch (uMsg) { case WM_INITDIALOG: // set text appropriately SetWindowText(hWnd, TEXT("Change Group")); // get PGROUP and set edit controls tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = g.hTreeItemWithMenu; TreeView_GetItem(g.hTreeWnd, &tvi); SendDlgItemMessage(hWnd, IDC_NAME, WM_SETTEXT, 0, (LPARAM)((PGROUP)tvi.lParam)->lpszName); BuildLineList(GetDlgItem(hWnd, IDC_LINECOMBO), (((PGROUP)tvi.lParam)->dwDeviceID)); BuildAddressList(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), hWnd, (((PGROUP)tvi.lParam)->dwAddress)); SetFocus(GetDlgItem(hWnd, IDC_NAME)); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_LINECOMBO: { if (HIWORD(wParam) == CBN_SELENDOK) { // need to redo addresses BuildAddressList(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), hWnd, 0); return 1; } return 0; } case IDOK: { TCHAR szName[128]; PGROUP pGroup; // get info SendDlgItemMessage(hWnd, IDC_NAME, WM_GETTEXT, 128, (LPARAM)szName); // get struct pGroup = (PGROUP)tvi.lParam; /// get device and address pGroup->dwDeviceID = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETCURSEL, 0, 0); pGroup->dwDeviceID = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETITEMDATA, (WPARAM)pGroup->dwDeviceID, 0); pGroup->dwAddress = SendDlgItemMessage(hWnd, IDC_ADDRESSCOMBO, CB_GETCURSEL, 0, 0); // save new info and free old info ACDFree(pGroup->lpszName); pGroup->lpszName = ACDAlloc((lstrlen(szName) + 1) * sizeof(TCHAR)); lstrcpy(pGroup->lpszName, szName); // update item name tvi.mask = TVIF_TEXT; tvi.pszText = szName; tvi.cchTextMax = lstrlen(szName) * sizeof(TCHAR); TreeView_SetItem(g.hTreeWnd, &tvi); EndDialog(hWnd, 1); return 1; } case IDCANCEL: { EndDialog(hWnd, 0); return 1; } default: return 0; } } return 0; } ////////////////////////////////////////////////////////////////////////////////// // // ChangeGroupDlgProc - Window proc for the change (properties) dialog box // for agents/groups // ////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK ChangeAgentDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static TV_ITEM tvi; switch (uMsg) { case WM_INITDIALOG: // set text appropriately SetWindowText(hWnd, TEXT("Change Agent")); // get PGROUP and set edit controls tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = g.hTreeItemWithMenu; TreeView_GetItem(g.hTreeWnd, &tvi); SendDlgItemMessage(hWnd, IDC_NAME, WM_SETTEXT, 0, (LPARAM)((PAGENT)tvi.lParam)->lpszName); SendDlgItemMessage(hWnd, IDC_DESTADDRESS, WM_SETTEXT, 0, (LPARAM)((PAGENT)tvi.lParam)->lpszNumber); BuildLineList(GetDlgItem(hWnd, IDC_LINECOMBO), (((PAGENT)tvi.lParam)->dwDeviceID)); SetFocus(GetDlgItem(hWnd, IDC_NAME)); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { TCHAR szName[128]; TCHAR szNumber[128]; PAGENT pAgent; // get info SendDlgItemMessage(hWnd, IDC_NAME, WM_GETTEXT, 128, (LPARAM)szName); SendDlgItemMessage(hWnd, IDC_DESTADDRESS, WM_GETTEXT, 128, (LPARAM)szNumber); // get struct pAgent = (PAGENT)tvi.lParam; /// get device and address pAgent->dwDeviceID = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETCURSEL, 0, 0); pAgent->dwDeviceID = SendDlgItemMessage(hWnd, IDC_LINECOMBO, CB_GETITEMDATA, (WPARAM)pAgent->dwDeviceID, 0); // save new info and free old info ACDFree(pAgent->lpszName); pAgent->lpszName = ACDAlloc((lstrlen(szName) + 1) * sizeof(TCHAR)); lstrcpy(pAgent->lpszName, szName); ACDFree(pAgent->lpszNumber); pAgent->lpszNumber = ACDAlloc((lstrlen(szNumber) + 1) * sizeof(TCHAR)); lstrcpy(pAgent->lpszNumber, szNumber); // update item name tvi.mask = TVIF_TEXT; tvi.pszText = szName; tvi.cchTextMax = lstrlen(szName) * sizeof(TCHAR); TreeView_SetItem(g.hTreeWnd, &tvi); EndDialog(hWnd, 1); return 1; } case IDCANCEL: { EndDialog(hWnd, 0); return 1; } default: return 0; } } return 0; } ////////////////////////////////////////////////////////////////////////////////////// // // AddToList() - Window proc for Add Agent To Group and Add Group To Agent // dialog box // ////////////////////////////////////////////////////////////////////////////////////// BOOL CALLBACK GroupAddToListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static PGROUP pGroup; PAGENT pAgent; PLISTITEM pList; TV_ITEM tvi; DWORD dwListBox; BOOL bFound; int item; TCHAR szBuffer[128]; switch (uMsg) { case WM_INITDIALOG: // get the item in question tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = g.hTreeItemWithMenu; TreeView_GetItem(g.hTreeWnd, &tvi); pGroup = (PGROUP)tvi.lParam; // init lists if (pGroup) { // initialize text in dialog wsprintf(szBuffer, TEXT("Add To %s"), pGroup->lpszName); SetWindowText(hWnd, TEXT("Add To Group")); SetDlgItemText(hWnd, IDC_STATICNOTINLIST, TEXT("Not in Group")); SetDlgItemText(hWnd, IDC_STATICINLIST, TEXT("Group Members")); pAgent = g.pAgents; // walk list and initialize list boxes while (pAgent) { pList = pGroup->pAgentList; bFound = FALSE; while (pList) { if (pList->pAgent == pAgent) { bFound = TRUE; break; } pList = pList->pNext; } // if it was found, it is already a member of // the group if (bFound) { dwListBox = IDC_LIST2; } else { dwListBox = IDC_LIST1; } // add to correct list box item = SendDlgItemMessage(hWnd, dwListBox, LB_ADDSTRING, 0, (LPARAM)pAgent->lpszName); // set the item data to be the item so we can get back it. if (item != LB_ERR) { SendDlgItemMessage(hWnd, dwListBox, LB_SETITEMDATA, (WPARAM)item, (LPARAM)pAgent); } pAgent = pAgent->pNext; } } return 1; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_ADD: { // get the item item = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0); if (item == 0) { if (!SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETSEL, (WPARAM)item, 0)) { item = -1; } } if (item != -1) { // get the PAGENT associated with it pAgent = (PAGENT)SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETITEMDATA, (WPARAM)item, 0); // delete it from this listbox SendDlgItemMessage(hWnd, IDC_LIST1, LB_DELETESTRING, (WPARAM)item, 0); // add it to this list box item = SendDlgItemMessage(hWnd, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)pAgent->lpszName); // set the item data again SendDlgItemMessage(hWnd, IDC_LIST2, LB_SETITEMDATA, item, (WPARAM)pAgent); // add it to the group's list InsertIntoGroupList(pGroup, pAgent); return 1; } } break; case IDC_REMOVE: { // get the item item = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0); if (item == 0) { if (!SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETSEL, (WPARAM)item, 0)) { item = -1; } } if (item != -1) { // get the struct associated with it pAgent = (PAGENT)SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETITEMDATA, (WPARAM)item, 0); // delete it from this list SendDlgItemMessage(hWnd, IDC_LIST2, LB_DELETESTRING, (WPARAM)item, 0); // add it to this list item = SendDlgItemMessage(hWnd, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)pAgent->lpszName); // set the item data SendDlgItemMessage(hWnd, IDC_LIST1, LB_SETITEMDATA, item, (WPARAM)pAgent); // remove it from the lists RemoveFromGroupList(pGroup, pAgent); return 1; } } break; // bug idcancel doesn't cancel case IDOK: case IDCANCEL: { UpdateGroupLeaf(pGroup); EndDialog(hWnd, 1); return 1; } default: return 0; } } return 0; } BOOL CALLBACK AgentAddToListProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static PAGENT pAgent; PGROUP pGroup; PLISTITEM pList; TV_ITEM tvi; DWORD dwListBox; BOOL bFound; int item; TCHAR szBuffer[128]; switch (uMsg) { case WM_INITDIALOG: // get the item in question tvi.mask = TVIF_HANDLE | TVIF_PARAM; tvi.hItem = g.hTreeItemWithMenu; TreeView_GetItem(g.hTreeWnd, &tvi); pAgent = (PAGENT)tvi.lParam; // init lists if (pAgent) { // initialize text in dialog wsprintf(szBuffer, TEXT("Add To %s"), pAgent->lpszName); SetWindowText(hWnd, TEXT("Add To Agent")); SetDlgItemText(hWnd, IDC_STATICNOTINLIST, TEXT("Not Member Of")); SetDlgItemText(hWnd, IDC_STATICINLIST, TEXT("Member Of")); pGroup = g.pGroups; // walk list and initialize list boxes while (pGroup) { pList = pGroup->pAgentList; bFound = FALSE; while (pList) { if (pList->pAgent == pAgent) { bFound = TRUE; break; } pList = pList->pNext; } // if it was found, it is already a member of // the group if (bFound) { dwListBox = IDC_LIST2; } else { dwListBox = IDC_LIST1; } // add to correct list box item = SendDlgItemMessage(hWnd, dwListBox, LB_ADDSTRING, 0, (LPARAM)pGroup->lpszName); // set the item data to be the item so we can get back it. if (item != LB_ERR) { SendDlgItemMessage(hWnd, dwListBox, LB_SETITEMDATA, (WPARAM)item, (LPARAM)pGroup); } pGroup = pGroup->pNext; } } return 1; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_ADD: { // get the item item = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0); if (item == 0) { if (!SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETSEL, (WPARAM)item, 0)) { item = -1; } } if (item != -1) { // get the PGROUP associated with it pGroup = (PGROUP)SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETITEMDATA, (WPARAM)item, 0); // delete it from this listbox SendDlgItemMessage(hWnd, IDC_LIST1, LB_DELETESTRING, (WPARAM)item, 0); // add it to this list box item = SendDlgItemMessage(hWnd, IDC_LIST2, LB_ADDSTRING, 0, (LPARAM)pGroup->lpszName); // set the item data again SendDlgItemMessage(hWnd, IDC_LIST2, LB_SETITEMDATA, item, (WPARAM)pGroup); // add it to the item's list InsertIntoGroupList(pGroup, pAgent); return 1; } } break; case IDC_REMOVE: { // get the item item = SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETCURSEL, 0, 0); if (item == 0) { if (!SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETSEL, (WPARAM)item, 0)) { item = -1; } } if (item != -1) { // get the struct associated with it pGroup = (PGROUP)SendDlgItemMessage(hWnd, IDC_LIST2, LB_GETITEMDATA, (WPARAM)item, 0); // delete it from this list SendDlgItemMessage(hWnd, IDC_LIST2, LB_DELETESTRING, (WPARAM)item, 0); // add it to this list item = SendDlgItemMessage(hWnd, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)pGroup->lpszName); // set the item data SendDlgItemMessage(hWnd, IDC_LIST1, LB_SETITEMDATA, item, (WPARAM)pGroup); // remove it from the lists RemoveFromGroupList(pGroup, pAgent); return 1; } } break; // bug idcancel doesn't cancel case IDOK: case IDCANCEL: { EndDialog(hWnd, 1); return 1; } default: return 0; } } return 0; } ////////////////////////////////////////////////////////////// // // BOOL DeleteLeafAndStruct(HTREEITEM hItem) // delete hItem from the tree and deleted associated // structure // ////////////////////////////////////////////////////////////// BOOL DeleteLeafAndStruct(HTREEITEM hItem) { TV_ITEM tvi; // get the item tvi.mask = TVIF_PARAM; tvi.hItem = hItem; TreeView_GetItem(g.hTreeWnd, &tvi); // delete the structure if (((PGENERICSTRUCT)tvi.lParam)->dwKey == GROUPKEY) { DeleteGroup((PGROUP)tvi.lParam); } else { DeleteAgent((PAGENT)tvi.lParam); } // remove it from the tree TreeView_DeleteItem(g.hTreeWnd, hItem); return TRUE; } //////////////////////////////////////////////////////////////////// // // BOOL BuildLineList(HWND hWnd, // DWORD dwDeviceID) // // Fill in ComboBox with names of all available TAPI // devices // //////////////////////////////////////////////////////////////////// BOOL BuildLineList(HWND hWnd, DWORD dwDeviceID) { DWORD dwDev; LPLINEDEVCAPS pLineDevCaps; int item; BOOL bSet = FALSE; // clear dropdown box SendMessage(hWnd, CB_RESETCONTENT, 0, 0); // loop through all devices for (dwDev = 0; dwDev < g.dwNumDevs; dwDev++) { pLineDevCaps = LineGetDevCaps(g.hLineApp, dwDev); // add the string to to list if (pLineDevCaps == NULL || pLineDevCaps->dwLineNameSize == 0) { item = SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)TEXT("NoName")); } else { item = SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)((LPTSTR)((LPBYTE)pLineDevCaps + pLineDevCaps->dwLineNameOffset))); } // save the device ID SendMessage(hWnd, CB_SETITEMDATA, item, dwDev); // if this is the device we are looking for // set it to be selected if (dwDev == dwDeviceID) { SendMessage(hWnd, CB_SETCURSEL, (WPARAM)item, 0); bSet = TRUE; } if (pLineDevCaps != NULL) { ACDFree((HLOCAL)pLineDevCaps); } } // if we didn't set the selection, default if (!bSet) { SendMessage(hWnd, CB_SETCURSEL, 0, 0); } return TRUE; } /////////////////////////////////////////////////////////////////////////////// // // BOOL BuildAddressList() // // Fill combo box with list of addresses on selected device ID // /////////////////////////////////////////////////////////////////////////////// BOOL BuildAddressList(HWND hWnd, HWND hParentWnd, DWORD dwAddress) { TCHAR szBuffer[32]; LPLINEDEVCAPS pLineDevCaps; LPLINEADDRESSCAPS pLineAddressCaps; DWORD dwCurAddress, dwDeviceID; int iCurSel; // clear box SendMessage(hWnd, CB_RESETCONTENT, 0, 0); // get the current selected device iCurSel = SendDlgItemMessage(hParentWnd, IDC_LINECOMBO, CB_GETCURSEL, 0, 0); // get associated deviceid dwDeviceID = (DWORD)SendDlgItemMessage(hParentWnd, IDC_LINECOMBO, CB_GETITEMDATA, (WPARAM)iCurSel, 0); pLineDevCaps = LineGetDevCaps(g.hLineApp, dwDeviceID); if (pLineDevCaps == NULL) return FALSE; // loop through all addresses for (dwCurAddress = 0; dwCurAddress < pLineDevCaps->dwNumAddresses; dwCurAddress++) { pLineAddressCaps = LineGetAddressCaps(g.hLineApp, dwDeviceID, dwCurAddress); // add name to list box if (pLineAddressCaps == NULL || pLineAddressCaps->dwAddressSize == 0) { wsprintf(szBuffer, TEXT("Address %d"), dwCurAddress); SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)szBuffer); } else { SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM)((LPTSTR)((LPBYTE)pLineAddressCaps + pLineAddressCaps->dwAddressOffset))); } ACDFree((HLOCAL)pLineAddressCaps); } SendMessage(hWnd, CB_SETCURSEL, (WPARAM)dwAddress, 0); ACDFree(pLineDevCaps); return TRUE; } /////////////////////////////////////////////////////////////////////////// // // BOOL UpdateGroupLeaf(PGROUP pStruct) // // Updates a group in the tree view when a new agent is added to that // group // /////////////////////////////////////////////////////////////////////////// BOOL UpdateGroupLeaf(PGROUP pStruct) { HTREEITEM hItem; PLISTITEM pItem; TV_ITEM tvi; // get the item's first child hItem = TreeView_GetChild(g.hTreeWnd, pStruct->hItem); while (hItem) { // delete all childre TreeView_DeleteItem(g.hTreeWnd, hItem); hItem = TreeView_GetChild(g.hTreeWnd, pStruct->hItem); } pItem = pStruct->pAgentList; // walk the agent list while (pItem) { // add all the agents hItem = AddItemToTree(pStruct->hItem, ((PAGENT)pItem->pAgent)->lpszName, (LPARAM)NULL, (HTREEITEM *)NULL); // if currently logged into that group /// bold that item if (pItem->bLoggedIn) { tvi.mask = TVIF_STATE | TVIF_HANDLE; tvi.hItem = hItem; tvi.state = TVIS_BOLD; tvi.stateMask = TVIS_BOLD; TreeView_SetItem(g.hTreeWnd, &tvi); } pItem = pItem->pNext; } return TRUE; } /////////////////////////////////////////////////////////////////////// // // BOOL DoGroupView() // // Display the tree in a "group view" (show groups, and under the // group, the agents that can log into that group) // /////////////////////////////////////////////////////////////////////// BOOL DoGroupView() { PGROUP pGroupParent, pGroup; TCHAR szGroupParentName[] = TEXT("Groups"); HTREEITEM hItem; TV_ITEM tvi; g.bGroupView = TRUE; // get the root hItem = TreeView_GetRoot(g.hTreeWnd); // free resources allocated for root if (hItem) { tvi.mask = TVIF_PARAM | TVIF_HANDLE; tvi.hItem = hItem; TreeView_GetItem(g.hTreeWnd, &tvi); ACDFree((PAGENT)tvi.lParam); } // clear tree TreeView_DeleteAllItems(g.hTreeWnd); // alloc memory for the structure for the Group parent pGroupParent = (PGROUP)ACDAlloc(sizeof(GROUP)); // alloc memory and copy the fixed name pGroupParent->lpszName = (LPTSTR)ACDAlloc((lstrlen(szGroupParentName) + 1) * sizeof(TCHAR)); pGroupParent->dwKey = GROUPROOTKEY; lstrcpy(pGroupParent->lpszName, szGroupParentName); // add it to the tree g.hGroupParent = AddItemToTree(TVI_ROOT, pGroupParent->lpszName, (LPARAM)pGroupParent, &pGroupParent->hItem); pGroup = g.pGroups; // walk groups and add them to tree while (pGroup) { AddItemToTree(g.hGroupParent, pGroup->lpszName, (LPARAM)pGroup, &pGroup->hItem); UpdateGroupLeaf(pGroup); pGroup = pGroup->pNext; } return TRUE; } //////////////////////////////////////////////////////////////////// // // BOOL DoAgentView() // // Displays the tree in an "agent view" // //////////////////////////////////////////////////////////////////// BOOL DoAgentView() { PAGENT pAgentParent,pAgent; TCHAR szAgentParentName[] = TEXT("Agents"); HTREEITEM hItem; TV_ITEM tvi; g.bGroupView = TRUE; // get root, free resources // and clear tree hItem = TreeView_GetRoot(g.hTreeWnd); if (hItem) { tvi.mask = TVIF_PARAM | TVIF_HANDLE; tvi.hItem = hItem; TreeView_GetItem(g.hTreeWnd, &tvi); ACDFree((PGROUP)tvi.lParam); } TreeView_DeleteAllItems(g.hTreeWnd); // alloc memory for the structure for the Agent parent pAgentParent = (PAGENT)ACDAlloc(sizeof(AGENT)); // alloc memory and copy the fixed name pAgentParent->lpszName = (LPTSTR)ACDAlloc((lstrlen(szAgentParentName) + 1) * sizeof(TCHAR)); pAgentParent->dwKey = GROUPROOTKEY; lstrcpy(pAgentParent->lpszName, szAgentParentName); // add it to the tree g.hAgentParent = AddItemToTree(TVI_ROOT, pAgentParent->lpszName, (LPARAM)pAgentParent, &pAgentParent->hItem); pAgent = g.pAgents; // walk agents and add all of them while (pAgent) { AddItemToTree(g.hAgentParent, pAgent->lpszName, (LPARAM)pAgent, &pAgent->hItem); pAgent = pAgent->pNext; } return TRUE; } ////////////////////////////////////////////////////////////////////////////////////// // // FOLLOWING ARE ROUTINES TO SAVE AND RESTORE GROUP / AGENT INFORMATION // // An INI file has been used for this implementation. // // This format is used to make it easy for users to create an INI file that can be // read in // // However, a real implementation // may want to use the registry, or a private data file to store more detailed and/or // secure information // // #define SZGROUPS TEXT("Groups") #define SZAGENTS TEXT("Agents") #define SZGROUP TEXT("GROUP") #define SZAGENT TEXT("AGENT") #define SZINIFILE TEXT("ACDSMPL.INI") #define SZGENERAL TEXT("General") #define SZNUMAGENTS TEXT("NumAgents") #define SZNUMGROUPS TEXT("NumGroups") ////////////////////////////////////////////////////////////////////////////// // // void MakeAgentIndex(PAGENT * ppAgents) // // creates an array of pagents // ////////////////////////////////////////////////////////////////////////////// void MakeAgentIndex(PAGENT * ppAgents) { PAGENT pAgent; pAgent = g.pAgents; while (pAgent) { *ppAgents = pAgent; pAgent = pAgent->pNext; ppAgents++; } } /////////////////////////////////////////////////////////////////////////////// // // int GetAgentIndex() // // retreives agent index // /////////////////////////////////////////////////////////////////////////////// int GetAgentIndex(PAGENT * ppAgents, PAGENT pAgent) { DWORD dwCount; for (dwCount = 0; dwCount < g.dwNumAgents; dwCount++) { if (ppAgents[dwCount] == pAgent) { return dwCount; } } return -1; } /////////////////////////////////////////////////////////////////////////////// // // BOOL WriteToDisk() // // save current group/agent config to acdsmpl.ini // /////////////////////////////////////////////////////////////////////////////// BOOL WriteToDisk() { int i; PGROUP pGroup; PAGENT pAgent; PLISTITEM pEntry; TCHAR szGroupName[32], szAgentName[32], szLineBuffer[512]; PAGENT * ppAgents; // create an index of agents ppAgents = (PAGENT *)ACDAlloc(sizeof(PAGENT) * g.dwNumAgents); MakeAgentIndex(ppAgents); pGroup = g.pGroups; i = 0; // walk groups while (pGroup) { wsprintf(szGroupName, TEXT("%s%d"), SZGROUP, i); wsprintf(szLineBuffer, TEXT("%s,%d,%d"), pGroup->lpszName, g.pdwPermIDs[pGroup->dwDeviceID], pGroup->dwAddress); // add group to [groups] section WritePrivateProfileString(SZGROUPS, szGroupName, szLineBuffer, SZINIFILE); pEntry = pGroup->pAgentList; // walk agents in group while (pEntry) { wsprintf(szAgentName, TEXT("%s%d"), SZAGENT, GetAgentIndex(ppAgents, pEntry->pAgent)); // write agent index to [groupx] section WritePrivateProfileString(szGroupName, szAgentName, TEXT("1"), SZINIFILE); pEntry = pEntry->pNext; } pGroup = pGroup->pNext; i++; } pAgent = g.pAgents; i = 0; //walk agents while (pAgent) { wsprintf(szAgentName, TEXT("%s%d"), SZAGENT, i); wsprintf(szLineBuffer, TEXT("%s,%s,%lu"), pAgent->lpszName, pAgent->lpszNumber, g.pdwPermIDs[pAgent->dwDeviceID]); // write agent to [agents] section WritePrivateProfileString(SZAGENTS, szAgentName, szLineBuffer, SZINIFILE); pAgent = pAgent->pNext; i++; } // save # of agents and groups wsprintf(szLineBuffer, TEXT("%lu"), g.dwNumGroups); WritePrivateProfileString(SZGENERAL, SZNUMGROUPS, szLineBuffer, SZINIFILE); wsprintf(szLineBuffer, TEXT("%lu"), g.dwNumAgents); WritePrivateProfileString(SZGENERAL, SZNUMAGENTS, szLineBuffer, SZINIFILE); ACDFree(ppAgents); return TRUE; } //////////////////////////////////////////////////////////////////////////////////// // // BOOL ReadInFile() // // Read in ACDSMPL.INI // //////////////////////////////////////////////////////////////////////////////////// BOOL ReadInFile() { TCHAR szAgentLabel[32], szGroupLabel[32]; DWORD dwID, dwAddress, dwNumAgents, dwNumGroups; DWORD dwCount, dwCount2; PAGENT * ppAgents = NULL; LPTSTR lpszName, lpszNumber, lpszDeviceID; LPTSTR lpszHold, szLineBuffer = NULL; PGROUP pGroup; dwNumAgents = GetPrivateProfileInt(SZGENERAL, SZNUMAGENTS, 0, SZINIFILE); dwNumGroups = GetPrivateProfileInt(SZGENERAL, SZNUMGROUPS, 0, SZINIFILE); ppAgents = (PAGENT *)ACDAlloc(sizeof(PAGENT) * dwNumAgents); szLineBuffer = (LPTSTR)ACDAlloc(512 * sizeof(WCHAR)); if (!ppAgents || !szLineBuffer) { ACDFree(ppAgents); ACDFree(szLineBuffer); return FALSE; } lpszHold = szLineBuffer; for (dwCount = 0; dwCount < dwNumAgents; dwCount++) { wsprintf(szAgentLabel, TEXT("%s%lu"), SZAGENT, dwCount); GetPrivateProfileString(SZAGENTS, szAgentLabel, TEXT(""), szLineBuffer, 512, SZINIFILE); lpszName = (LPTSTR)szLineBuffer; while (szLineBuffer && *szLineBuffer) { if (*szLineBuffer == TEXT(',')) { *szLineBuffer = TEXT('\0'); szLineBuffer++; break; } szLineBuffer++; } lpszNumber = (LPTSTR)szLineBuffer; while (szLineBuffer && *szLineBuffer) { if (*szLineBuffer == TEXT(',')) { *szLineBuffer = TEXT('\0'); szLineBuffer++; dwID = _wtol(szLineBuffer); dwID = GetDeviceID(dwID); ppAgents[dwCount] = AddAgent(lpszName, lpszNumber, dwID); break; } szLineBuffer++; } } for (dwCount = 0; dwCount < dwNumGroups; dwCount++) { wsprintf(szGroupLabel, TEXT("%s%lu"), SZGROUP, dwCount); GetPrivateProfileString(SZGROUPS, szGroupLabel, TEXT(""), szLineBuffer, 512, SZINIFILE); lpszName = (LPTSTR)szLineBuffer; while (szLineBuffer && *szLineBuffer) { if (*szLineBuffer == TEXT(',')) { *szLineBuffer = TEXT('\0'); szLineBuffer++; lpszDeviceID = szLineBuffer; break; } szLineBuffer++; } while (szLineBuffer && *szLineBuffer) { if (*szLineBuffer == TEXT(',')) { *szLineBuffer = TEXT('\0'); szLineBuffer++; dwAddress = _wtol(szLineBuffer); break; } szLineBuffer++; } dwID = _wtol(lpszDeviceID); dwID = GetDeviceID(dwID); pGroup = AddGroup(lpszName, dwID, dwAddress); if (!pGroup) { continue; } for (dwCount2 = 0; dwCount2 < dwNumAgents; dwCount2++) { wsprintf(szAgentLabel, TEXT("%s%lu"), SZAGENT, dwCount2); if (GetPrivateProfileString(szGroupLabel, szAgentLabel, TEXT(""), szLineBuffer, 512, SZINIFILE) != 0) { InsertIntoGroupList(pGroup, ppAgents[dwCount2]); } } // for dwcount2 } // for dwcount ACDFree(ppAgents); ACDFree(lpszHold); DoGroupView(); return TRUE; }