void Subsets_GetSubsetFromDialog (HWND hDlg, LPSUBSET sub) { HWND hList = GetDlgItem (hDlg, IDC_SUBSET_LIST); if (sub->pszMonitored) { FreeString (sub->pszMonitored); sub->pszMonitored = NULL; } if (sub->pszUnmonitored) { FreeString (sub->pszUnmonitored); sub->pszUnmonitored = NULL; } // Is there only one server box checked? // int iiMax = (int) SendMessage (hList, LB_GETCOUNT, 0, 0); size_t cChecked = 0; int iiChecked; for (int ii = 0; ii < iiMax; ++ii) { if (LB_GetCheck (hList, ii)) { iiChecked = ii; if ((++cChecked) > 1) break; } } if (cChecked == 1) // Only one is checked--use pszMonitored. { TCHAR szServer[ cchNAME ]; SendMessage (hList, LB_GETTEXT, iiChecked, (LPARAM)szServer); FormatMultiString (&sub->pszMonitored, TRUE, TEXT("%1"), TEXT("%s"), szServer); } else // Use pszUnmonitored. { for (int ii = 0; ii < iiMax; ++ii) { if (!LB_GetCheck (hList, ii)) { TCHAR szServer[ cchNAME ]; SendMessage (hList, LB_GETTEXT, ii, (LPARAM)szServer); FormatMultiString (&sub->pszUnmonitored, TRUE, TEXT("%1"), TEXT("%s"), szServer); } } } }
LPSUBSET Subsets_LoadSubset (LPTSTR pszCell, LPTSTR pszSubset) { LPSUBSET sub = NULL; HKEY hk; if ((hk = OpenSubsetsSubKey (pszCell, pszSubset, FALSE)) != NULL) { DWORD dwMonitored; DWORD dwSize; DWORD dwType; dwSize = sizeof(dwMonitored); if (RegQueryValueEx (hk, REGVAL_INCLUSIVE, 0, &dwType, (LPBYTE)&dwMonitored, &dwSize) == 0) { sub = New (SUBSET); memset (sub, 0x00, sizeof(SUBSET)); lstrcpy (sub->szSubset, pszSubset); sub->fModified = FALSE; LPTSTR *ppsz; ppsz = (dwMonitored) ? &sub->pszMonitored : &sub->pszUnmonitored; for (size_t iIndex = 0; ; ++iIndex) { TCHAR szServer[ cchNAME ]; dwSize = sizeof(szServer); if (RegEnumValue (hk, (DWORD)iIndex, szServer, &dwSize, 0, NULL, NULL, NULL) != 0) break; if (szServer[0] && lstrcmpi (szServer, REGVAL_INCLUSIVE)) FormatMultiString (ppsz, FALSE, TEXT("%1"), TEXT("%s"), szServer); } if (dwMonitored && !sub->pszMonitored) { sub->pszMonitored = AllocateString(2); sub->pszMonitored[0] = TEXT('\0'); sub->pszMonitored[1] = TEXT('\0'); } } RegCloseKey (hk); } return sub; }
BOOL Group_Create_OnOK (HWND hDlg) { LPCREATEGROUPDLG lpp = (LPCREATEGROUPDLG)GetWindowLongPtr (hDlg, DWLP_USER); // Start a background task to do all the work. // LPGROUP_CREATE_PARAMS pTask = New (GROUP_CREATE_PARAMS); memset (pTask, 0x00, sizeof(GROUP_CREATE_PARAMS)); if (IsDlgButtonChecked (hDlg, IDC_NEWGROUP_ID_AUTO)) pTask->idGroup = UID_AUTOSELECT; else // (IsDlgButtonChecked (hDlg, IDC_NEWGROUP_ID_MANUAL)) pTask->idGroup = SP_GetPos (GetDlgItem (hDlg, IDC_NEWGROUP_ID)); lstrcpy (pTask->Properties.szOwner, lpp->Advanced.szOwner); pTask->Properties.aaListStatus = lpp->Advanced.aaStatus; pTask->Properties.aaListGroupsOwned = lpp->Advanced.aaGroups; pTask->Properties.aaListMembers = lpp->Advanced.aaMembers; pTask->Properties.aaAddMember = lpp->Advanced.aaAdd; pTask->Properties.aaDeleteMember = lpp->Advanced.aaRemove; if (lpp->Advanced.pMembers) asc_AsidListCopy (&pTask->pMembers, &lpp->Advanced.pMembers); else pTask->pMembers = NULL; if (lpp->Advanced.pGroupsOwner) asc_AsidListCopy (&pTask->pGroupsOwner, &lpp->Advanced.pGroupsOwner); else pTask->pGroupsOwner = NULL; // Crack the specified list of user names into a multi-string // TCHAR szSeparators[ cchRESOURCE ]; GetString (szSeparators, IDS_SEPARATORS); lstrcat (szSeparators, TEXT(" \t")); LPTSTR pszNames = GetEditText (GetDlgItem (hDlg, IDC_NEWGROUP_NAME)); LPCTSTR pszStart = pszNames; while (lstrchr (szSeparators, *pszStart)) ++pszStart; while (*pszStart) { // Find the first non-name character // LPCTSTR pszEnd = pszStart; while (*pszEnd && !lstrchr(szSeparators, *pszEnd)) ++pszEnd; // Copy off this particular name // TCHAR szName[ cchNAME ]; lstrcpy (szName, pszStart); szName[ pszEnd - pszStart ] = TEXT('\0'); if (szName[0]) FormatMultiString (&pTask->mszNames, FALSE, TEXT("%1"), TEXT("%s"), szName); // Find the next valid-name character // pszStart = pszEnd; while (lstrchr(szSeparators, *pszStart)) ++pszStart; } FreeString (pszNames); // Do the real work of creating the user(s) // StartTask (taskGROUP_CREATE, NULL, pTask); // Store these creation parameters as the new defaults // memcpy (&gr.CreateGroup, &lpp->Advanced, sizeof(GROUPPROPINFO)); return TRUE; }
CMDLINEOP ParseCommandLine (LPTSTR pszCmdLine) { size_t ii; for (ii = 0; ii < nSWITCHES; ++ii) aSWITCHES[ ii ].fPresent = FALSE; // Search through pszCmdLine for switches; each switch must be // preceeded by "/" or "-". // while (pszCmdLine && *pszCmdLine) { while (iswhite(*pszCmdLine)) ++pszCmdLine; if (!*pszCmdLine) break; if ( (*pszCmdLine != '-') && (*pszCmdLine != '/') ) { CommandLineHelp (IDS_CMDLINE_SYNTAX); return opCLOSEAPP; } ++pszCmdLine; // Okay, we've found what is probably the start of a switch. // See if it matches anything. // for (ii = 0; ii < nSWITCHES; ++ii) { size_t cch = lstrlen(aSWITCHES[ ii ].szSwitch); if (lstrncmpi (pszCmdLine, aSWITCHES[ ii ].szSwitch, cch)) continue; // If the switch wants a value, it must be followed by ":" // or whitespace; if it doesn't, it must be followed by "/" // or whitespace. // LPTSTR pszAfter = &pszCmdLine[ cch ]; if (iswhite (*pszAfter) || (!*pszAfter) || ((*pszAfter == TEXT(':')) && (aSWITCHES[ ii ].fGetsValue)) || ((*pszAfter == TEXT('/')) && (!aSWITCHES[ ii ].fGetsValue)) ) { break; // found a switch! } } if (ii >= nSWITCHES) { TCHAR szCopy[ cchRESOURCE ]; lstrcpy (szCopy, pszCmdLine); LPTSTR pch; for (pch = szCopy; *pch && !iswhite(*pch) && !(*pch == TEXT('/')) && !(*pch == TEXT(':')); ++pch) ; *pch = TEXT('\0'); CommandLineHelp (IDS_CMDLINE_UNRECOGNIZED, TEXT("%s"), szCopy); return opCLOSEAPP; } if (aSWITCHES[ ii ].fPresent) { CommandLineHelp (IDS_CMDLINE_DUPLICATE, TEXT("%s"), aSWITCHES[ ii ].szSwitch); return opCLOSEAPP; } // Woo hoo! Found what appears to be a valid switch. Parse it now. // aSWITCHES[ ii ].fPresent = TRUE; pszCmdLine += lstrlen( aSWITCHES[ ii ].szSwitch ); while (iswhite (*pszCmdLine)) ++pszCmdLine; if (*pszCmdLine == TEXT(':')) { if (!aSWITCHES[ ii ].fGetsValue) { CommandLineHelp (IDS_CMDLINE_UNEXPECTVALUE, TEXT("%s"), aSWITCHES[ ii ].szSwitch); return opCLOSEAPP; } for (++pszCmdLine; iswhite (*pszCmdLine); ++pszCmdLine) ; } if (aSWITCHES[ ii ].fGetsValue) { if ( (*pszCmdLine == TEXT('/')) || (*pszCmdLine == TEXT('\0')) ) { CommandLineHelp (IDS_CMDLINE_MISSINGVAL, TEXT("%s"), aSWITCHES[ ii ].szSwitch); return opCLOSEAPP; } BOOL fQuoted = FALSE; LPTSTR pszTarget; for (pszTarget = aSWITCHES[ ii ].szValue; *pszCmdLine && !(*pszCmdLine == TEXT('/') && !fQuoted) && !(iswhite(*pszCmdLine) && !fQuoted); ) { if (*pszCmdLine == TEXT('"')) { ++pszCmdLine; if (fQuoted) break; fQuoted = TRUE; continue; } *pszTarget++ = *pszCmdLine++; } *pszTarget++ = TEXT('\0'); } } // Was the -CONFIRM switch given? It works with any other switch // combination. // if (aSWITCHES[ swCONFIRM ].fPresent) { Action_ShowConfirmations (TRUE); } // Now test the command-line for syntactical correctness. // First test: if the SUBSET switch is given, the CELL switch must // be given as well. // if ( (aSWITCHES[ swSUBSET ].fPresent) && (!aSWITCHES[ swCELL ].fPresent) ) { CommandLineHelp (IDS_CMDLINE_SUBSETNOTCELL); return opCLOSEAPP; } // Similarly, if the SERVER switch is given, the CELL switch must // be given as well. // if ( (aSWITCHES[ swSERVER ].fPresent) && (!aSWITCHES[ swCELL ].fPresent) ) { CommandLineHelp (IDS_CMDLINE_SERVERNOTCELL); return opCLOSEAPP; } // And if the USER or PASSWORD switch is given, the other is required. // if ( (aSWITCHES[ swUSER ].fPresent && !aSWITCHES[ swPASSWORD ].fPresent) || (aSWITCHES[ swPASSWORD ].fPresent && !aSWITCHES[ swUSER ].fPresent) ) { CommandLineHelp (IDS_CMDLINE_USERPASSWORD); return opCLOSEAPP; } // Implement the command-line switches. // if (aSWITCHES[ swRESET ].fPresent) { if (aSWITCHES[ swSERVER ].fPresent) { ErasePreferences (aSWITCHES[ swCELL ].szValue, aSWITCHES[ swSERVER ].szValue); } else if (aSWITCHES[ swCELL ].fPresent) { ErasePreferences (aSWITCHES[ swCELL ].szValue); } else // neither cell nor server specified--kill just the general stuff { EraseSettings (REGSTR_SETTINGS_BASE, REGSTR_SETTINGS_PATH, REGVAL_SETTINGS); } Message (MB_OK | MB_ICONINFORMATION, IDS_CMDLINE_RESET_TITLE, IDS_CMDLINE_RESET_DESC); return opCLOSEAPP; } if (aSWITCHES[ swUSER ].fPresent) { LPTSTR pszCell = (aSWITCHES[ swCELL ].fPresent) ? (aSWITCHES[ swCELL ].szValue) : NULL; ULONG status; if (!AfsAppLib_SetCredentials (pszCell, aSWITCHES[ swUSER ].szValue, aSWITCHES[ swPASSWORD ].szValue, &status)) { ImmediateErrorDialog (status, IDS_SVR_ERROR_BAD_CREDENTIALS); return opCLOSEAPP; } } if (aSWITCHES[ swLOOKUP ].fPresent) { return opLOOKUPERRORCODE; } if (aSWITCHES[ swUSEEXISTING ].fPresent) { ULONG ulStatus; TCHAR szDefCell[ cchNAME ]; if (aSWITCHES[ swCELL ].fPresent) { lstrcpy(szDefCell,aSWITCHES[ swCELL ].szValue); } else { AfsAppLib_GetLocalCell(szDefCell); } g.hCreds = AfsAppLib_GetCredentials(szDefCell,&ulStatus); if (g.hCreds != NULL) { LPOPENCELL_PACKET lpocp = New (OPENCELL_PACKET); memset(lpocp,0x00,sizeof(OPENCELL_PACKET)); lstrcpy(lpocp->szCell,szDefCell); lpocp->fCloseAppOnFail = TRUE; lpocp->hCreds = g.hCreds; lpocp->sub = NULL; StartTask(taskOPENCELL,NULL,lpocp); return opNOCELLDIALOG; } else return opCLOSEAPP; } if (aSWITCHES[ swCELL ].fPresent) { LPOPENCELL_PACKET lpp = New (OPENCELL_PACKET); memset (lpp, 0x00, sizeof(OPENCELL_PACKET)); lstrcpy (lpp->szCell, aSWITCHES[ swCELL ].szValue); lpp->fCloseAppOnFail = TRUE; if (aSWITCHES[ swSUBSET ].fPresent) { lpp->sub = Subsets_LoadSubset (lpp->szCell, aSWITCHES[ swSUBSET ].szValue); if (lpp->sub == NULL) { Delete (lpp); lpp = NULL; CommandLineHelp (IDS_CMDLINE_INVALIDSUBSET, TEXT("%s%s"), aSWITCHES[ swCELL ].szValue, aSWITCHES[ swSUBSET ].szValue); return opCLOSEAPP; } } else if (aSWITCHES[ swSERVER ].fPresent) { lpp->sub = New (SUBSET); memset (lpp->sub, 0x0, sizeof(SUBSET)); FormatMultiString (&lpp->sub->pszMonitored, TRUE, TEXT("%1"), TEXT("%s"), aSWITCHES[ swSERVER ].szValue); } StartTask (taskOPENCELL, NULL, lpp); return opNOCELLDIALOG; } // Okay--nothing sufficiently special took place to prevent us // from running the tool normally. // return opNORMAL; }
BOOL USER::RefreshStatus (BOOL fNotify, ULONG *pStatus) { BOOL rc = TRUE; DWORD status = 0; DWORD kasStatus = 0; DWORD ptsStatus = 0; if (m_fStatusOutOfDate) { m_fStatusOutOfDate = FALSE; if (fNotify) NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier()); memset (&m_us, 0x00, sizeof(m_us)); FreeString (m_mszOwnerOf); m_mszOwnerOf = NULL; FreeString (m_mszMemberOf); m_mszMemberOf = NULL; TCHAR szFullName[ cchNAME ]; AfsClass_GenFullUserName (szFullName, m_szPrincipal, m_szInstance); LPCELL lpCell; if ((lpCell = OpenCell (&status)) == NULL) rc = FALSE; else { PVOID hCell; if ((hCell = lpCell->GetCellObject (&status)) == NULL) rc = FALSE; else { // Try to get KAS information. // WORKERPACKET wpGetKas; wpGetKas.wpKasPrincipalGet.hCell = hCell; wpGetKas.wpKasPrincipalGet.hServer = lpCell->GetKasObject (&kasStatus); wpGetKas.wpKasPrincipalGet.pszPrincipal = m_szPrincipal; wpGetKas.wpKasPrincipalGet.pszInstance = m_szInstance; if (Worker_DoTask (wtaskKasPrincipalGet, &wpGetKas, &kasStatus)) { m_us.fHaveKasInfo = TRUE; TCHAR szLastModPrincipal[ cchNAME ]; TCHAR szLastModInstance[ cchNAME ]; CopyAnsiToString (szLastModPrincipal, wpGetKas.wpKasPrincipalGet.Data.lastModPrincipal.principal); CopyAnsiToString (szLastModInstance, wpGetKas.wpKasPrincipalGet.Data.lastModPrincipal.instance); m_us.KASINFO.fIsAdmin = (wpGetKas.wpKasPrincipalGet.Data.adminSetting == KAS_ADMIN) ? TRUE : FALSE; m_us.KASINFO.fCanGetTickets = (wpGetKas.wpKasPrincipalGet.Data.tgsSetting == TGS) ? TRUE : FALSE; m_us.KASINFO.fEncrypt = (wpGetKas.wpKasPrincipalGet.Data.encSetting == ENCRYPT) ? TRUE : FALSE; m_us.KASINFO.fCanChangePassword = (wpGetKas.wpKasPrincipalGet.Data.cpwSetting == CHANGE_PASSWORD) ? TRUE : FALSE; m_us.KASINFO.fCanReusePasswords = (wpGetKas.wpKasPrincipalGet.Data.rpwSetting == REUSE_PASSWORD) ? TRUE : FALSE; AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeExpires, wpGetKas.wpKasPrincipalGet.Data.userExpiration); AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeLastPwChange, wpGetKas.wpKasPrincipalGet.Data.lastChangePasswordTime); AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeLastMod, wpGetKas.wpKasPrincipalGet.Data.lastModTime); m_us.KASINFO.lpiLastMod = IDENT::FindUser (m_lpiCell, szLastModPrincipal, szLastModInstance); m_us.KASINFO.csecTicketLifetime = wpGetKas.wpKasPrincipalGet.Data.maxTicketLifetime; m_us.KASINFO.keyVersion = wpGetKas.wpKasPrincipalGet.Data.keyVersion; memcpy (&m_us.KASINFO.key.key, &wpGetKas.wpKasPrincipalGet.Data.key.key, ENCRYPTIONKEY_LEN); m_us.KASINFO.dwKeyChecksum = wpGetKas.wpKasPrincipalGet.Data.keyCheckSum; m_us.KASINFO.cdayPwExpire = wpGetKas.wpKasPrincipalGet.Data.daysToPasswordExpire; m_us.KASINFO.cFailLogin = wpGetKas.wpKasPrincipalGet.Data.failLoginCount; m_us.KASINFO.csecFailLoginLock = wpGetKas.wpKasPrincipalGet.Data.lockTime; } // Try to get PTS information. // WORKERPACKET wpGetPts; wpGetPts.wpPtsUserGet.hCell = hCell; wpGetPts.wpPtsUserGet.pszUser = szFullName; if (Worker_DoTask (wtaskPtsUserGet, &wpGetPts, &ptsStatus)) { m_us.fHavePtsInfo = TRUE; m_us.PTSINFO.cgroupCreationQuota = wpGetPts.wpPtsUserGet.Entry.groupCreationQuota; m_us.PTSINFO.cgroupMember = wpGetPts.wpPtsUserGet.Entry.groupMembershipCount; m_us.PTSINFO.uidName = wpGetPts.wpPtsUserGet.Entry.nameUid; m_us.PTSINFO.uidOwner = wpGetPts.wpPtsUserGet.Entry.ownerUid; m_us.PTSINFO.uidCreator = wpGetPts.wpPtsUserGet.Entry.creatorUid; CopyAnsiToString (m_us.PTSINFO.szOwner, wpGetPts.wpPtsUserGet.Entry.owner); CopyAnsiToString (m_us.PTSINFO.szCreator, wpGetPts.wpPtsUserGet.Entry.creator); m_us.PTSINFO.aaListStatus = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listStatus); m_us.PTSINFO.aaGroupsOwned = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listGroupsOwned); m_us.PTSINFO.aaMembership = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listMembership); } // Grab the list of groups to which this user belongs // WORKERPACKET wpBegin; wpBegin.wpPtsUserMemberListBegin.hCell = hCell; wpBegin.wpPtsUserMemberListBegin.pszUser = szFullName; if (Worker_DoTask (wtaskPtsUserMemberListBegin, &wpBegin, &status)) { for (;;) { TCHAR szGroup[ cchNAME ]; WORKERPACKET wpNext; wpNext.wpPtsUserMemberListNext.hEnum = wpBegin.wpPtsUserMemberListBegin.hEnum; wpNext.wpPtsUserMemberListNext.pszGroup = szGroup; if (!Worker_DoTask (wtaskPtsUserMemberListNext, &wpNext)) break; FormatMultiString (&m_mszMemberOf, FALSE, TEXT("%1"), TEXT("%s"), szGroup); } WORKERPACKET wpDone; wpDone.wpPtsUserMemberListDone.hEnum = wpBegin.wpPtsUserMemberListBegin.hEnum; Worker_DoTask (wtaskPtsUserMemberListDone, &wpDone); } // Grab the list of groups which this user owns // wpBegin.wpPtsOwnedGroupListBegin.hCell = hCell; wpBegin.wpPtsOwnedGroupListBegin.pszOwner = szFullName; if (Worker_DoTask (wtaskPtsOwnedGroupListBegin, &wpBegin, &status)) { for (;;) { TCHAR szGroup[ cchNAME ]; WORKERPACKET wpNext; wpNext.wpPtsOwnedGroupListNext.hEnum = wpBegin.wpPtsOwnedGroupListBegin.hEnum; wpNext.wpPtsOwnedGroupListNext.pszGroup = szGroup; if (!Worker_DoTask (wtaskPtsOwnedGroupListNext, &wpNext)) break; FormatMultiString (&m_mszOwnerOf, FALSE, TEXT("%1"), TEXT("%s"), szGroup); } WORKERPACKET wpDone; wpDone.wpPtsOwnedGroupListDone.hEnum = wpBegin.wpPtsOwnedGroupListBegin.hEnum; Worker_DoTask (wtaskPtsOwnedGroupListDone, &wpDone); } } lpCell->Close(); } if (fNotify) NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status)); } if (rc && (!m_us.fHaveKasInfo) && (!status) && kasStatus) { status = kasStatus; rc = FALSE; } if (rc && (!m_us.fHavePtsInfo) && (!status) && ptsStatus) { status = ptsStatus; // not fatal; rc remains TRUE } if (pStatus && !rc) *pStatus = status; return TRUE; }
LPSUBSET Subsets_SetMonitor (LPSUBSET sub, LPIDENT lpiServer, BOOL fMonitor) { if (sub == NULL) { sub = New (SUBSET); memset (sub, 0x00, sizeof(SUBSET)); } if (fMonitor != Subsets_fMonitorServer (sub, lpiServer)) { sub->fModified = TRUE; TCHAR szLong[ cchNAME ]; TCHAR szShort[ cchNAME ]; lpiServer->GetShortServerName (szShort); lpiServer->GetLongServerName (szLong); // First ensure that the server name doesn't appear anywhere // in the subset. // LPTSTR pszMonitoredNew = NULL; LPTSTR pszUnmonitoredNew = NULL; if (sub->pszMonitored) { for (LPTSTR psz = sub->pszMonitored; *psz; psz += 1+lstrlen(psz)) { if (lstrcmpi (psz, szLong) && lstrcmpi (psz, szShort)) { FormatMultiString (&pszMonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), psz); } } } else if (sub->pszUnmonitored) { for (LPTSTR psz = sub->pszUnmonitored; *psz; psz += 1+lstrlen(psz)) { if (lstrcmpi (psz, szLong) && lstrcmpi (psz, szShort)) { FormatMultiString (&pszUnmonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), psz); } } } // Then ensure it shows up only where necessary. // if (sub->pszMonitored && fMonitor) { FormatMultiString (&pszMonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), szLong); } else if (!sub->pszMonitored && !fMonitor) { FormatMultiString (&pszUnmonitoredNew, TRUE, TEXT("%1"), TEXT("%s"), szLong); } if (sub->pszMonitored && !pszMonitoredNew) { pszMonitoredNew = AllocateString (2); pszMonitoredNew[0] = TEXT('\0'); pszMonitoredNew[1] = TEXT('\0'); } if (sub->pszUnmonitored && !pszUnmonitoredNew) { pszUnmonitoredNew = AllocateString (2); pszUnmonitoredNew[0] = TEXT('\0'); pszUnmonitoredNew[1] = TEXT('\0'); } // Finally, update the subset's members. // if (sub->pszMonitored) FreeString (sub->pszMonitored); if (sub->pszUnmonitored) FreeString (sub->pszUnmonitored); sub->pszMonitored = pszMonitoredNew; sub->pszUnmonitored = pszUnmonitoredNew; } return sub; }