// Copyright (c) 1995, Microsoft Corporation, all rights reserved // // util.c // Remote Access Common Dialog APIs // Utility routines // Listed alphabetically // // Steve Cobb 06/20/95 #include "rasdlgp.h" // Our private header #include // Common dialog resource constants #include // NetWkstaGetInfo #include // NetApiBufferFree #include // machine is a member of a workgroup or domain, etc. #include typedef struct _COUNT_FREE_COM_PORTS_DATA { DTLLIST* pListPortsInUse; DWORD dwCount; } COUNT_FREE_COM_PORTS_DATA; const WCHAR c_szCurrentBuildNumber[] = L"CurrentBuildNumber"; const WCHAR c_szWinVersionPath[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; const WCHAR c_szNt40BuildNumber[] = L"1381"; //----------------------------------------------------------------------------- // Help maps //----------------------------------------------------------------------------- static DWORD g_adwPnHelp[] = { CID_LE_ST_Item, HID_PN_EB_NewNumber, CID_LE_EB_Item, HID_PN_EB_NewNumber, CID_LE_PB_Add, HID_PN_PB_Add, CID_LE_PB_Replace, HID_PN_PB_Replace, CID_LE_ST_List, HID_PN_LB_List, CID_LE_LB_List, HID_PN_LB_List, CID_LE_PB_Up, HID_PN_PB_Up, CID_LE_PB_Down, HID_PN_PB_Down, CID_LE_PB_Delete, HID_PN_PB_Delete, CID_LE_CB_Promote, HID_PN_CB_Promote, 0, 0 }; //----------------------------------------------------------------------------- // Local helper prototypes (alphabetically) //----------------------------------------------------------------------------- BOOL CountFreeComPorts( IN PWCHAR pszPort, IN HANDLE hData); //----------------------------------------------------------------------------- // Utility routines (alphabetically) //----------------------------------------------------------------------------- BOOL AllLinksAreModems( IN PBENTRY* pEntry ) // Returns true if all links associated with the entry are modem links // (MXS or Unimodem), false otherwise. // { DTLNODE* pNode; if (pEntry->pdtllistLinks) { for (pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); pNode; pNode = DtlGetNextNode( pNode )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNode ); if (pLink->pbport.pbdevicetype != PBDT_Modem) { return FALSE; } } } return TRUE; } BOOL AllowDccWizard( IN HANDLE hConnection) // Finds out if there are any dcc devices installed on the local // machine or if there are any available com ports. If neither // condition is satisfied, then we return FALSE, otherwise TRUE. { DWORD dwErr, dwUsedCount = 0; COUNT_FREE_COM_PORTS_DATA CountFreeComPortsData, *pCfcpd = &CountFreeComPortsData; DTLNODE* pNodeP, *pNodeL, *pNode; BOOL bRet = FALSE; // Initialize ZeroMemory(pCfcpd, sizeof(COUNT_FREE_COM_PORTS_DATA)); do { // Load ras if it wasn't already loaded dwErr = LoadRas( g_hinstDll, NULL ); if (dwErr != 0) { return FALSE; } // Load in all of the ports and count the number of // dcc devices dwErr = LoadPortsList2( hConnection, &(pCfcpd->pListPortsInUse), FALSE); if (dwErr != NO_ERROR) { bRet = FALSE; break; } // Count the dcc devices for (pNodeL = DtlGetFirstNode( pCfcpd->pListPortsInUse ); pNodeL; pNodeL = DtlGetNextNode( pNodeL )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNodeL ); if (pLink->pbport.dwType == RASET_Direct) { bRet = TRUE; break; } } if (bRet == TRUE) { break; } // pmay: 249346 // // Only merge the com ports if the user is an admin since // admin privilege is required to install a null modem. // if (FIsUserAdminOrPowerUser()) { // Count the number of available com ports dwErr = MdmEnumComPorts ( CountFreeComPorts, (HANDLE)pCfcpd); if (dwErr != NO_ERROR) { bRet = FALSE; break; } bRet = (pCfcpd->dwCount > 0) ? TRUE : FALSE; } } while (FALSE); // Cleanup { if ( pCfcpd->pListPortsInUse ) { DtlDestroyList(pCfcpd->pListPortsInUse, DestroyPortNode); } } return bRet; } DWORD AuthRestrictionsFromTypicalAuth( IN DWORD dwTypicalAuth ) // Return the AR_F_* flag corresponding to the TA_* value 'dwTypicalAuth', // i.e. convert a typical authentication selection to a bitmask of // authentication protocols. // { if (dwTypicalAuth == TA_Secure) { return AR_F_TypicalSecure; } else if (dwTypicalAuth == TA_CardOrCert) { return AR_F_TypicalCardOrCert; } else { return AR_F_TypicalUnsecure; } } LONG GetGlobalCallbackActive( ) { LONG ret = 0; __try { EnterCriticalSection( &g_csCallBacks ); ret = g_ulCallbacksActive; TRACE1("GlobalActive Calls are:%ld",g_ulCallbacksActive); } __finally { LeaveCriticalSection( &g_csCallBacks ); } return ret; } LONG IncGlobalCallbackActive( ) { LONG ret = 0; __try { EnterCriticalSection( &g_csCallBacks ); g_ulCallbacksActive++; ret = g_ulCallbacksActive; TRACE1("GlobalActive Calls are:%ld",g_ulCallbacksActive); } __finally { LeaveCriticalSection( &g_csCallBacks ); } return ret; } LONG DecGlobalCallbackActive( ) { LONG ret = 0; __try { EnterCriticalSection( &g_csCallBacks ); if( 0 < g_ulCallbacksActive ) { g_ulCallbacksActive -- ; } ret = g_ulCallbacksActive; TRACE1("GlobalActive Calls are:%ld", g_ulCallbacksActive); } __finally { LeaveCriticalSection( &g_csCallBacks ); } return ret; } ULONG CallbacksActive( INT nSetTerminateAsap, BOOL* pfTerminateAsap ) // If 'fSetTerminateAsap' >= 0, sets 'g_fTerminateAsap' flag to 'nSetTerminateAsap'. // If non-NULL, caller's '*pfTerminateAsap' is filled with the current value of // 'g_fTerminateAsap'. // // Returns the number of Rasdial callback threads active. // { ULONG ul; TRACE1( "CallbacksActive(%d)", nSetTerminateAsap ); ul = 0; //For XPSP2 511810 and .Net 668164 // __try { EnterCriticalSection( &g_csCallBacks ); if (pfTerminateAsap) { *pfTerminateAsap = g_fTerminateAsap; } if (nSetTerminateAsap >= 0) { g_fTerminateAsap = (BOOL )nSetTerminateAsap; } ul = g_ulCallbacksActive; } __finally { LeaveCriticalSection( &g_csCallBacks ); } TRACE1( "CallbacksActive=%d", ul ); return ul; } VOID ContextHelp( IN const DWORD* padwMap, IN HWND hwndDlg, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam) { ContextHelpX( padwMap, hwndDlg, unMsg, wparam, lparam, FALSE ); } VOID ContextHelpX( IN const DWORD* padwMap, IN HWND hwndDlg, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam, IN BOOL fRouter) // Calls WinHelp to popup context sensitive help. 'PadwMap' is an array // of control-ID help-ID pairs terminated with a 0,0 pair. 'UnMsg' is // WM_HELP or WM_CONTEXTMENU indicating the message received requesting // help. 'Wparam' and 'lparam' are the parameters of the message received // requesting help. // { HWND hwnd; UINT unType; TCHAR* pszHelpFile; ASSERT( unMsg==WM_HELP || unMsg==WM_CONTEXTMENU ); // Don't try to do help if it won't work. See common\uiutil\ui.c. // { extern BOOL g_fNoWinHelp; if (g_fNoWinHelp) { return; } } if (unMsg == WM_HELP) { LPHELPINFO p = (LPHELPINFO )lparam; TRACE3( "ContextHelp(WM_HELP,t=%d,id=%d,h=$%08x)", p->iContextType, p->iCtrlId,p->hItemHandle ); if (p->iContextType != HELPINFO_WINDOW) { return; } hwnd = p->hItemHandle; ASSERT( hwnd ); unType = HELP_WM_HELP; } else { // Standard Win95 method that produces a one-item "What's This?" menu // that user must click to get help. // TRACE1( "ContextHelp(WM_CONTEXTMENU,h=$%08x)", wparam ); hwnd = (HWND )wparam; unType = HELP_CONTEXTMENU; }; if (fRouter) { pszHelpFile = g_pszRouterHelpFile; } else { pszHelpFile = g_pszHelpFile; } TRACE1( "WinHelp(%s)", pszHelpFile ); WinHelp( hwnd, pszHelpFile, unType, (ULONG_PTR ) padwMap ); } VOID CopyLinkPhoneNumberInfo( OUT DTLNODE* pDstLinkNode, IN DTLNODE* pSrcLinkNode ) // Copies the source link's phone number information to the destination // link. Any existing destination information is properly destroyed. The // arguments are DTLNODEs containing PBLINKs. // { PBLINK* pSrcLink; PBLINK* pDstLink; DTLLIST* pDstList; pSrcLink = (PBLINK* )DtlGetData( pSrcLinkNode ); pDstLink = (PBLINK* )DtlGetData( pDstLinkNode ); pDstList = DtlDuplicateList( pSrcLink->pdtllistPhones, DuplicatePhoneNode, DestroyPhoneNode ); if (pDstList) { DtlDestroyList( pDstLink->pdtllistPhones, DestroyPhoneNode ); pDstLink->pdtllistPhones = pDstList; pDstLink->fPromoteAlternates = pSrcLink->fPromoteAlternates; pDstLink->fTryNextAlternateOnFail = pSrcLink->fTryNextAlternateOnFail; } } VOID CopyPszListToPhoneList( IN OUT PBLINK* pLink, IN DTLLIST* pListPhoneNumbers ) // Converts the phone number list of 'pLink' to be list created using the // the list of Psz phone numbers 'pListPhoneNumbers' for phone numbers. // { DTLNODE* pNodeP; DTLNODE* pNodeZ; // Empty the existing list of PBPHONE nodes. // while (pNodeP = DtlGetFirstNode( pLink->pdtllistPhones )) { DtlRemoveNode( pLink->pdtllistPhones, pNodeP ); DestroyPhoneNode( pNodeP ); } // Recreate the list of PBPHONE nodes from the list of PSZ nodes. // for (pNodeZ = DtlGetFirstNode( pListPhoneNumbers ); pNodeZ; pNodeZ = DtlGetNextNode( pNodeZ )) { PBPHONE* pPhone; pNodeP = CreatePhoneNode(); if (!pNodeP) { continue; } pPhone = (PBPHONE* )DtlGetData( pNodeP ); ASSERT( pPhone ); Free0( pPhone->pszPhoneNumber ); pPhone->pszPhoneNumber = StrDup( (TCHAR* )DtlGetData( pNodeZ ) ); DtlAddNodeLast( pLink->pdtllistPhones, pNodeP ); } } BOOL CountFreeComPorts( IN PWCHAR pszPort, IN HANDLE hData) // Com port enumeration function that counts the list of // free com ports. Returns TRUE to stop enumeration (see // MdmEnumComPorts) { COUNT_FREE_COM_PORTS_DATA* pfcpData = (COUNT_FREE_COM_PORTS_DATA*)hData; DTLLIST* pListUsed = pfcpData->pListPortsInUse; DTLNODE* pNodeP, *pNodeL, *pNode; // If the given port is in the used list, then return // so that it is not added to the list of free ports and // so that enumeration continues. for (pNodeL = DtlGetFirstNode( pListUsed ); pNodeL; pNodeL = DtlGetNextNode( pNodeL )) { PBLINK* pLink = (PBLINK* )DtlGetData( pNodeL ); ASSERT( pLink->pbport.pszPort ); // The port already appears in a link in the list. if (lstrcmp( pLink->pbport.pszPort, pszPort ) == 0) return FALSE; } // The port is not in use. Increment the count. pfcpData->dwCount += 1; return FALSE; } HWND CreateWizardBitmap( IN HWND hwndDlg, IN BOOL fPage ) // Create a static control that displays the RAS wizard bitmap at the // standard place on dialog 'hwndDlg'. 'FPage' is set if the bitmap is // being placed on a property page, false for the equivalent placement on // a dialog. // // Returns the bitmap window handle or NULL or error. // { HWND hwnd; INT x; INT y; if (fPage) { x = y = 0; } else { x = y = 10; } hwnd = CreateWindowEx( 0, TEXT("static"), NULL, WS_VISIBLE | WS_CHILD | SS_SUNKEN | SS_BITMAP, x, y, 80, 140, hwndDlg, (HMENU )CID_BM_Wizard, g_hinstDll, NULL ); if (hwnd) { if (!g_hbmWizard) { g_hbmWizard = LoadBitmap( g_hinstDll, MAKEINTRESOURCE( BID_Wizard ) ); } SendMessage( hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM )g_hbmWizard ); } return hwnd; } TCHAR* DisplayPszFromDeviceAndPort( IN TCHAR* pszDevice, IN TCHAR* pszPort ) // Returns address of heap block psz containing the MXS modem list display // form, i.e. the device name 'pszDevice' followed by the port name // 'pszPort'. It's caller's responsibility to Free the returned string. // { TCHAR* pszResult; TCHAR* pszD; if (pszDevice) { pszD = NULL; } else { pszD = pszDevice = PszFromId( g_hinstDll, SID_UnknownDevice ); } pszResult = PszFromDeviceAndPort( pszDevice, pszPort ); Free0( pszD ); return pszResult; } TCHAR* DisplayPszFromPpbport( IN PBPORT* pPort, OUT DWORD* pdwDeviceIcon ) // Returns address of heap block psz containing the device display form of // the 'pPort', e.g. "Modem - KTel 28.8 Fax Plus" It's caller's // responsibility to Free the returned string. If non-NULL, // '*pdwDeviceIcon' is set to the DI_* device icon code corresponding to // the device. DI_* codes are used with the RAS ListView extensions to // show the correct item icon. // { TCHAR* pszFormat; TCHAR* pszD; TCHAR* pszDT; TCHAR* pszDevice; TCHAR* pszDeviceType; TCHAR* pszResult; DWORD dwDeviceIcon; LPCTSTR pszChannel = NULL; // These are set if a resource string is read that must be Freed later. // pszDT = NULL; pszD = NULL; if (pPort->pszDevice) { pszDevice = pPort->pszDevice; } else { pszDevice = PszFromId( g_hinstDll, SID_UnknownDevice ); if(NULL == pszDevice) { return NULL; } pszD = pszDevice; } // Set default format and device icon, though they may be changed below. // pszFormat = TEXT("%s - %s (%s)"); dwDeviceIcon = DI_Adapter; if (pPort->pbdevicetype == PBDT_Modem && !(pPort->dwFlags & PBP_F_NullModem)) { pszDeviceType = PszFromId( g_hinstDll, SID_Modem ); pszDT = pszDeviceType; dwDeviceIcon = DI_Modem; } else if (pPort->pbdevicetype == PBDT_Isdn) { pszDeviceType = PszFromId( g_hinstDll, SID_Isdn ); pszDT = pszDeviceType; pszFormat = TEXT("%s %s - %s"); } else if (pPort->pbdevicetype == PBDT_X25) { pszDeviceType = PszFromId( g_hinstDll, SID_X25 ); pszDT = pszDeviceType; } else if (pPort->pbdevicetype == PBDT_Pad) { pszDeviceType = PszFromId( g_hinstDll, SID_X25Pad ); pszDT = pszDeviceType; } else { // Don't know the device type, so just bag the device descriptive word // and let the device name stand alone. // pszDeviceType = TEXT(""); pszFormat = TEXT("%s%s (%s)"); } if(NULL == pszDeviceType) { pszDeviceType = TEXT(""); } if(pPort->pbdevicetype != PBDT_Isdn) { pszResult = Malloc( (lstrlen( pszFormat ) + lstrlen( pszDeviceType ) + lstrlen( pszDevice ) + lstrlen( pPort->pszPort )) * sizeof(TCHAR) ); } else { pszChannel = PszLoadString( g_hinstDll, SID_Channel ); if(NULL == pszChannel) { pszChannel = TEXT(""); } // For isdn use the following format // "Isdn channel - // Talk to steve falcon about this if you have issues // with special casing isdn. // pszResult = Malloc( (lstrlen( pszFormat ) + lstrlen( pszDeviceType ) + lstrlen(pszChannel) + lstrlen( pszDevice )) * sizeof(TCHAR)); } if (pszResult) { if(pPort->pbdevicetype != PBDT_Isdn) { wsprintf( pszResult, pszFormat, pszDeviceType, pszDevice, pPort->pszPort); } else { ASSERT(NULL != pszChannel); wsprintf( pszResult, pszFormat, pszDeviceType, pszChannel, pszDevice); } } if (pdwDeviceIcon) { #if 1 // Per SteveFal. Wants "modem" icon for all if Device-Manager-style // physically descriptive icons cannot be used. // dwDeviceIcon = DI_Modem; #endif *pdwDeviceIcon = dwDeviceIcon; } Free0( pszD ); Free0( pszDT ); return pszResult; } VOID EnableCbWithRestore( IN HWND hwndCb, IN BOOL fEnable, IN BOOL fDisabledCheck, IN OUT BOOL* pfRestore ) // Enable/disable the checkbox 'hwndCb' based on the 'fEnable' flag // including stashing and restoring a cached value '*pfRestore' when // disabled. When disabling, the check value is set to 'fDisabledCheck'. // { if (fEnable) { if (!IsWindowEnabled( hwndCb )) { // Toggling to enabled. Restore the stashed check value. // Button_SetCheck( hwndCb, *pfRestore ); EnableWindow( hwndCb, TRUE ); } } else { if (IsWindowEnabled( hwndCb )) { // Toggling to disabled. Stashed the current check value. // *pfRestore = Button_GetCheck( hwndCb ); Button_SetCheck( hwndCb, fDisabledCheck ); EnableWindow( hwndCb, FALSE ); } } } VOID EnableLbWithRestore( IN HWND hwndLb, IN BOOL fEnable, IN OUT INT* piRestore ) // Enable/disable the combobox 'hwndLb' based on the 'fEnable' flag. If // disabling, '*piRestore' is loaded with the stashed selection index and // a blank item is added to the front of the list and selected. This is // undone if enabling. // { if (fEnable) { if (!IsWindowEnabled( hwndLb )) { // Toggling to enabled. Restore the stashed selection. // ComboBox_DeleteString( hwndLb, 0 ); ComboBox_SetCurSelNotify( hwndLb, *piRestore ); EnableWindow( hwndLb, TRUE ); } } else { if (IsWindowEnabled( hwndLb )) { // Toggling to disabled. Stash the selection index. // *piRestore = ComboBox_GetCurSel( hwndLb ); ComboBox_InsertString( hwndLb, 0, TEXT("") ); ComboBox_SetItemData( hwndLb, 0, NULL ); ComboBox_SetCurSelNotify( hwndLb, 0 ); EnableWindow( hwndLb, FALSE ); } } } DTLNODE* FirstPhoneNodeFromPhoneList( IN DTLLIST* pListPhones ) // Return the first PBPHONE node in list of PBPHONEs 'pListPhones' or a // default node if none. Returns NULL if out of memory. // { DTLNODE* pFirstNode; DTLNODE* pNode; pFirstNode = DtlGetFirstNode( pListPhones ); if (pFirstNode) { pNode = DuplicatePhoneNode( pFirstNode ); } else { pNode = CreatePhoneNode(); } return pNode; } VOID FirstPhoneNodeToPhoneList( IN DTLLIST* pListPhones, IN DTLNODE* pNewNode ) // Replace the first PBPHONE node in list of PBPHONEs 'pListPhones' with // 'pNewNode', deleting any existing first node. Caller's actual // 'pNewNode', not a copy, is linked. // { DTLNODE* pFirstNode; DTLNODE* pNode; pFirstNode = DtlGetFirstNode( pListPhones ); if (pFirstNode) { DtlRemoveNode( pListPhones, pFirstNode ); DestroyPhoneNode( pFirstNode ); } DtlAddNodeFirst( pListPhones, pNewNode ); } #if 0 //!!! TCHAR* FirstPhoneNumberFromEntry( IN PBENTRY* pEntry ) // Returns the first phone number of the first link of entry 'pEntry' or // an empty string if none. The returned address is into the list of // phone numbers and should be copied if it needs to be stored. // { TCHAR* pszPhoneNumber; DTLNODE* pNode; PBLINK* pLink; TRACE( "FirstPhoneNumberFromEntry" ); ASSERT( pEntry->pdtllistLinks ); pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNode ); pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); return FirstPszFromList( pLink->pdtllistPhoneNumbers ); } #endif TCHAR* FirstPszFromList( IN DTLLIST* pPszList ) // Returns the first string from the first node of 'pPszList' or an empty // string if none. The returned address is into the list and should be // copied if it needs to be stored. // { TCHAR* psz; DTLNODE* pNode; TRACE( "FirstPszFromList" ); if (DtlGetNodes( pPszList ) > 0) { pNode = DtlGetFirstNode( pPszList ); ASSERT( pNode ); psz = (TCHAR* )DtlGetData( pNode ); ASSERT( psz ); } else { psz = TEXT(""); } return psz; } #if 0 //!!! DWORD FirstPhoneNumberToEntry( IN PBENTRY* pEntry, IN TCHAR* pszPhoneNumber ) // Sets the first phone number of the first link of entry 'pEntry' to // 'pszPhoneNumber'. // // Returns 0 if successful, or an error code. // { DTLNODE* pNode; PBLINK* pLink; TCHAR* pszNew; TRACE( "FirstPhoneNumberToEntry" ); ASSERT( pEntry->pdtllistLinks ); pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNode ); pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); ASSERT( pLink->pdtllistPhoneNumbers ); return FirstPszToList( pLink->pdtllistPhoneNumbers, pszPhoneNumber ); } #endif DWORD FirstPszToList( IN DTLLIST* pPszList, IN TCHAR* psz ) // Sets the string of the first node of the list 'pPszList' to a copy of // 'psz'. If 'psz' is "" the first node is deleted. // // Returns 0 if successful, or an error code. // { DTLNODE* pNode; TCHAR* pszNew; ASSERT( pPszList ); // Delete the existing first node, if any. // if (DtlGetNodes( pPszList ) > 0) { pNode = DtlGetFirstNode( pPszList ); DtlRemoveNode( pPszList, pNode ); DestroyPszNode( pNode ); } // Create a new first node and link it. An empty string is not added. // if (*psz == TEXT('\0')) return 0; pszNew = StrDup( psz ); pNode = DtlCreateNode( pszNew, 0 ); if (!pszNew || !pNode) { Free0( pszNew ); return ERROR_NOT_ENOUGH_MEMORY; } DtlAddNodeFirst( pPszList, pNode ); return 0; } // // Function: GetBoldWindowFont // // Purpose: Generate bold or large bold fonts based on the font of the // window specified // // Parameters: hwnd [IN] - Handle of window to base font on // fLargeFont [IN] - If TRUE, generate a 12 point bold font for // use in the wizard "welcome" page. // pBoldFont [OUT] - The newly generated font, NULL if the // // Returns: nothing // VOID GetBoldWindowFont( IN HWND hwnd, IN BOOL fLargeFont, OUT HFONT * pBoldFont) { LOGFONT BoldLogFont; HFONT hFont; TCHAR FontSizeString[MAX_PATH]; INT FontSize; HDC hdc; *pBoldFont = NULL; // Get the font used by the specified window // hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L); if (NULL == hFont) { // If not found then the control is using the system font // hFont = (HFONT)GetStockObject(SYSTEM_FONT); } if (hFont) { // Get the font info so we can generate the BOLD version // if (GetObject(hFont, sizeof(BoldLogFont), &BoldLogFont)) { // Create the Bold Font // BoldLogFont.lfWeight = FW_BOLD; hdc = GetDC(hwnd); if (hdc) { // Large (tall) font is an option // if (fLargeFont) { // Load size and name from resources, // since these may change // from locale to locale based on the // size of the system font, etc. // UINT nLen; PWCHAR pszFontName = NULL, pszFontSize = NULL; pszFontName = (PWCHAR)PszLoadString( g_hinstDll, SID_LargeFontName); pszFontSize = (PWCHAR)PszLoadString( g_hinstDll, SID_LargeFontSize); if (pszFontName != NULL) { lstrcpyn( BoldLogFont.lfFaceName, pszFontName, sizeof(BoldLogFont.lfFaceName) / sizeof(TCHAR)); } FontSize = 12; nLen = lstrlen(pszFontName); if (pszFontSize) { lstrcpyn( FontSizeString, pszFontSize, sizeof(FontSizeString) / sizeof(TCHAR)); FontSize = wcstoul((const TCHAR*)FontSizeString, NULL, 10); } BoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72); //Free0(pszFontName); //Free0(pszFontSize); } *pBoldFont = CreateFontIndirect(&BoldLogFont); ReleaseDC(hwnd, hdc); } } } } DWORD GetDefaultEntryName( IN PBFILE* pFile, IN DWORD dwType, IN BOOL fRouter, OUT TCHAR** ppszName ) // Loads a default entry name into '*ppszName' that is unique within open // phonebook 'pFile', or if NULL, in all default phonebooks. 'FRouter' is // set if a router-style name should be chosen rather than a client-style // name. It is caller's responsibility to Free the returned string. // // Returns 0 if successful or an error code. // { DWORD dwErr; TCHAR szBuf[ RAS_MaxEntryName + 1 ]; UINT unSid; LPCTSTR pszDefault; DWORD dwDefaultLen; LONG lNum; PBFILE file; DTLNODE* pNode; *ppszName = NULL; if (fRouter) { unSid = SID_DefaultRouterEntryName; } else { unSid = SID_DefaultEntryName; if (RASET_Vpn == dwType) { unSid = SID_DefaultVpnEntryName; } else if (RASET_Direct == dwType) { unSid = SID_DefaultDccEntryName; } else if (RASET_Broadband == dwType) { unSid = SID_DefaultBbEntryName; } } pszDefault = PszLoadString( g_hinstDll, unSid ); lstrcpyn( szBuf, pszDefault, sizeof(szBuf) / sizeof(TCHAR) ); dwDefaultLen = lstrlen( pszDefault ) + 1; // +1 for extra space below lNum = 2; for (;;) { if (pFile) { if (!EntryNodeFromName( pFile->pdtllistEntries, szBuf )) { break; } } else { if (GetPbkAndEntryName( NULL, szBuf, RPBF_NoCreate, &file, &pNode ) == 0) { ClosePhonebookFile( &file ); } else { break; } } // Duplicate entry found so increment the default name and try the // next one. // lstrcpyn( szBuf, pszDefault, sizeof(szBuf) / sizeof(TCHAR) ); lstrcat( szBuf, TEXT(" ")); LToT( lNum, szBuf + dwDefaultLen, 10 ); ++lNum; } *ppszName = StrDup( szBuf ); if (!*ppszName) { return ERROR_NOT_ENOUGH_MEMORY; } return ERROR_SUCCESS; } BOOL IsLocalPad( IN PBENTRY* pEntry ) // Returns true if 'pEntry' is a local PAD device, i.e. the first link of // the entry has device type "pad", false otherwise. // { PBLINK* pLink; DTLNODE* pNode; if (!pEntry) { return FALSE; } ASSERT( pEntry->pdtllistLinks ); pNode = DtlGetFirstNode( pEntry->pdtllistLinks ); ASSERT( pNode ); pLink = (PBLINK* )DtlGetData( pNode ); ASSERT( pLink ); return (pLink->pbport.pbdevicetype == PBDT_Pad); } #if 0 //---------------------------------------------------------------------------- // Function: IsNt40Machine // // Returns whether the given machine is running nt40 //---------------------------------------------------------------------------- DWORD IsNt40Machine ( IN PWCHAR pszServer, OUT PBOOL pbIsNt40) { DWORD dwErr, dwType = REG_SZ, dwLength; HKEY hkMachine, hkVersion; WCHAR pszBuildNumber[64]; PWCHAR pszMachine = NULL; // // Validate and initialize // if (!pbIsNt40) { return ERROR_INVALID_PARAMETER; } *pbIsNt40 = FALSE; do { // Format the machine name if ( (pszServer) && (wcslen(pszServer) > 0) ) { dwLength = wcslen( pszServer ) + 3; pszMachine = (PWCHAR) Malloc ( dwLength * sizeof( WCHAR ) ); if (pszMachine == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } if ( *pszMachine == L'\\' ) { wcscpy( pszMachine, pszServer ); } else { wcscpy( pszMachine, L"\\\\" ); wcscat( pszMachine, pszServer ); } } else { pszMachine = NULL; } // // Connect to the remote server // dwErr = RegConnectRegistry( pszMachine, HKEY_LOCAL_MACHINE, &hkMachine); if ( dwErr != ERROR_SUCCESS ) { break; } // // Open the windows version key // dwErr = RegOpenKeyEx( hkMachine, c_szWinVersionPath, 0, KEY_ALL_ACCESS, &hkVersion ); if ( dwErr != NO_ERROR ) { break; } // // Read in the current version key // dwLength = sizeof(pszBuildNumber); dwErr = RegQueryValueEx ( hkVersion, c_szCurrentBuildNumber, NULL, &dwType, (BYTE*)pszBuildNumber, &dwLength ); if (dwErr != NO_ERROR) { break; } if (lstrcmp (pszBuildNumber, c_szNt40BuildNumber) == 0) { *pbIsNt40 = TRUE; } } while (FALSE); // Cleanup { if ( hkVersion ) { RegCloseKey( hkVersion ); } if ( hkMachine ) { RegCloseKey( hkMachine ); } Free0( pszMachine ); } return dwErr; } #endif BOOL PhoneNodeIsBlank( IN DTLNODE* pNode ) // Returns true if the phone number in PBPHONE node 'pNode' is "blank", // i.e. it contains no area code, phone number, or comment strings. // { PBPHONE* pPhone; pPhone = (PBPHONE* )DtlGetData( pNode ); ASSERT( pPhone ); if ((!pPhone->pszAreaCode || IsAllWhite( pPhone->pszAreaCode )) && (!pPhone->pszPhoneNumber || IsAllWhite( pPhone->pszPhoneNumber )) && (!pPhone->pszComment || IsAllWhite( pPhone->pszComment ))) { return TRUE; } return FALSE; } BOOL PhoneNumberDlg( IN HWND hwndOwner, IN BOOL fRouter, IN OUT DTLLIST* pList, IN OUT BOOL* pfCheck ) // Popup the phone number list dialog. 'HwndOwner' is the owner of the // created dialog. 'FRouter' indicates router-style labels should be used // rather than client-style. 'PList' is a list of Psz nodes containing // the phone numbers. 'PfCheck' is the address that contains the initial // "promote number" checkbox setting and which receives the value set by // user. // // Returns true if user presses OK and succeeds, false if he presses // Cancel or encounters an error. // { DWORD sidHuntTitle; DWORD sidHuntItemLabel; DWORD sidHuntListLabel; DWORD sidHuntCheckLabel; //For whistler bug 227538 TCHAR *pszTitle = NULL, *pszItem = NULL, *pszList = NULL, *pszCheck = NULL; DWORD dwErr = NO_ERROR; TRACE( "PhoneNumberDlg" ); if (fRouter) { sidHuntTitle = SID_RouterHuntTitle; sidHuntItemLabel = SID_RouterHuntItemLabel; sidHuntListLabel = SID_RouterHuntListLabel; sidHuntCheckLabel = SID_RouterHuntCheckLabel; } else { sidHuntTitle = SID_HuntTitle; sidHuntItemLabel = SID_HuntItemLabel; sidHuntListLabel = SID_HuntListLabel; sidHuntCheckLabel = SID_HuntCheckLabel; } pszTitle = PszFromId( g_hinstDll, sidHuntTitle ); pszItem = PszFromId( g_hinstDll, sidHuntItemLabel ); pszList = PszFromId( g_hinstDll, sidHuntListLabel ); pszCheck = PszFromId( g_hinstDll, sidHuntCheckLabel ); dwErr=ListEditorDlg( hwndOwner, pList, pfCheck, RAS_MaxPhoneNumber, pszTitle, pszItem, pszList, pszCheck, NULL, 0, g_adwPnHelp, 0, NULL ); Free0( pszTitle ); Free0( pszItem ); Free0( pszList ); Free0( pszCheck ); return dwErr; } VOID PositionDlg( IN HWND hwndDlg, IN BOOL fPosition, IN LONG xDlg, IN LONG yDlg ) // Positions the dialog 'hwndDlg' based on caller's API settings, where // 'fPosition' is the RASxxFLAG_PositionDlg flag and 'xDlg' and 'yDlg' are // the coordinates. // { if (fPosition) { // Move it to caller's coordinates. // SetWindowPos( hwndDlg, NULL, xDlg, yDlg, 0, 0, SWP_NOZORDER + SWP_NOSIZE ); UnclipWindow( hwndDlg ); } else { // Center it on the owner window, or on the screen if none. // CenterWindow( hwndDlg, GetParent( hwndDlg ) ); } } LRESULT CALLBACK PositionDlgStdCallWndProc( int code, WPARAM wparam, LPARAM lparam ) // Standard Win32 CallWndProc hook callback that positions the next dialog // to start in this thread at our standard offset relative to owner. // { // Arrive here when any window procedure associated with our thread is // called. // if (!wparam) { CWPSTRUCT* p = (CWPSTRUCT* )lparam; // The message is from outside our process. Look for the MessageBox // dialog initialization message and take that opportunity to position // the dialog at the standard place relative to the calling dialog. // if (p->message == WM_INITDIALOG) { RECT rect; HWND hwndOwner; hwndOwner = GetParent( p->hwnd ); GetWindowRect( hwndOwner, &rect ); SetWindowPos( p->hwnd, NULL, rect.left + DXSHEET, rect.top + DYSHEET, 0, 0, SWP_NOZORDER + SWP_NOSIZE ); UnclipWindow( p->hwnd ); } } return 0; } TCHAR* PszFromPhoneNumberList( IN DTLLIST* pList ) // Returns the phone numbers in phone number list 'pList' in a comma // string or NULL on error. It is caller's responsiblity to Free the // returned string. // { TCHAR* pszResult, *pszTemp; DTLNODE* pNode; DWORD cb; const TCHAR* pszSeparator = TEXT(", "); cb = (DtlGetNodes( pList ) * (RAS_MaxPhoneNumber + lstrlen( pszSeparator )) + 1) * sizeof(TCHAR); pszResult = Malloc( cb ); if (!pszResult) { return NULL; } *pszResult = TEXT('\0'); for (pNode = DtlGetFirstNode( pList ); pNode; pNode = DtlGetNextNode( pNode )) { TCHAR* psz = (TCHAR* )DtlGetData( pNode ); ASSERT( psz ); if (*pszResult) lstrcat( pszResult, pszSeparator ); lstrcat( pszResult, psz ); } pszTemp = Realloc( pszResult, (lstrlen( pszResult ) + 1) * sizeof(TCHAR) ); ASSERT( pszTemp ); if (pszTemp) { pszResult = pszTemp; } return pszResult; } #if 0 LRESULT CALLBACK SelectDesktopCallWndRetProc( int code, WPARAM wparam, LPARAM lparam ) // Standard Win32 CallWndRetProc hook callback that makes "Desktop" the // initial selection of the FileOpen "Look in" combo-box. // { // Arrive here when any window procedure associated with our thread is // called. // if (!wparam) { CWPRETSTRUCT* p = (CWPRETSTRUCT* )lparam; // The message is from outside our process. Look for the MessageBox // dialog initialization message and take that opportunity to set the // "Look in:" combo box to the first item, i.e. "Desktop". FileOpen // keys off CBN_CLOSEUP rather than CBN_SELCHANGE to update the // "contents" listbox. // if (p->message == WM_INITDIALOG) { HWND hwndLbLookIn; hwndLbLookIn = GetDlgItem( p->hwnd, cmb2 ); ComboBox_SetCurSel( hwndLbLookIn, 0 ); SendMessage( p->hwnd, WM_COMMAND, MAKELONG( cmb2, CBN_CLOSEUP ), (LPARAM )hwndLbLookIn ); } } return 0; } #endif //We want to get rid of the Icon resources from rasdlg, they take too much //memory resource. instead, we retrieve them from netman.dll, if failed, we //use the default one IID_Broadband gangz //Also, for whistler bug 372078 364763 364876 // HICON GetCurrentIconEntryType( IN DWORD dwType, IN BOOL fSmall) { HICON hIcon = NULL; DWORD dwSize, dwConnectionIcon; HRESULT hr = E_FAIL; NETCON_MEDIATYPE ncm; HMODULE hNetshell = NULL; HRESULT (WINAPI * pHrGetIconFromMediaType) (DWORD , NETCON_MEDIATYPE , NETCON_SUBMEDIATYPE , DWORD , DWORD , HICON *); dwSize = fSmall ? 16 : 32; switch (dwType) { case RASET_Direct: { ncm = NCM_DIRECT; break; } case RASET_Vpn: { ncm = NCM_TUNNEL; break; } case RASET_Broadband: { ncm = NCM_PPPOE; break; } case RASET_Phone: default: { ncm = NCM_PHONE; break; } } hNetshell = LoadLibrary(TEXT("netshell.dll")); if( hNetshell ) { pHrGetIconFromMediaType =(HRESULT (WINAPI*)( DWORD , NETCON_MEDIATYPE , NETCON_SUBMEDIATYPE , DWORD , DWORD , HICON *) )GetProcAddress( hNetshell, "HrGetIconFromMediaType"); if ( NULL != pHrGetIconFromMediaType ) { /******************************************************************* ** dwConnectionIcon - (This is the little Computer part of the icon): ** 0 - no connection overlay ** 4 - Connection Icon with both lights off (Disabled status) ** 5 - Connection Icon with left light on (Transmitting Data) ** 6 - Connection Icon with right light on (Receiving Data) ** 7 - Connection Icon with both lights on (Enabled status) *********************************************************************/ dwConnectionIcon = 7; hr = pHrGetIconFromMediaType(dwSize, ncm, NCSM_NONE, 7, 0, &hIcon); } FreeLibrary( hNetshell ); } if ( !SUCCEEDED(hr) || !hIcon) { ICONINFO iInfo; HICON hTemp; hTemp = LoadIcon( g_hinstDll, MAKEINTRESOURCE( IID_Broadband ) ); if(hTemp) { if( GetIconInfo(hTemp, &iInfo) ) { hIcon = CreateIconIndirect(&iInfo); } } } return hIcon; } VOID SetIconFromEntryType( IN HWND hwndIcon, IN DWORD dwType, IN BOOL fSmall) // Set the icon image of icon control 'dwType' to the image corresponding // to the entry type 'dwType'. // { HICON hIcon = NULL; hIcon = GetCurrentIconEntryType( dwType, fSmall ); if (hIcon) { Static_SetIcon( hwndIcon, hIcon ); } } VOID TweakTitleBar( IN HWND hwndDlg ) // Adjust the title bar to include an icon if unowned and the modal frame // if not. 'HwndDlg' is the dialog window. // { if (GetParent( hwndDlg )) { LONG lStyle; LONG lStyleAdd; // Drop the system menu and go for the dialog look. // lStyleAdd = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE; lStyle = GetWindowLong( hwndDlg, GWL_EXSTYLE ); if (lStyle) SetWindowLong( hwndDlg, GWL_EXSTYLE, lStyle | lStyleAdd ); } else { // Stick a DUN1 icon in the upper left of the dialog, and more // importantly on the task bar // // Whistler bug: 343455 RAS: Connection dialogs need to use new icons // //For whistler bug 381099 372078 gangz // HICON hIcon = NULL; SendMessage( hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM )LoadIcon( g_hinstDll, MAKEINTRESOURCE( IID_Dun1 ) ) ); /* //Use small Icon gangz //Icon returned from GetCurrentIconEntryType() has to be destroyed after use //In the future, Deonb will return a Icon for IID_Dun1 or dun1.ico for us. hIcon = GetCurrentIconEntryType(RASET_Broadband , TRUE); ASSERT(hIcon); if(hIcon) { SendMessage( hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)(hIcon) ); SetProp( hwndDlg, TEXT("TweakTitleBar_Icon"), hIcon); } */ } } int CALLBACK UnHelpCallbackFunc( IN HWND hwndDlg, IN UINT unMsg, IN LPARAM lparam ) // A standard Win32 commctrl PropSheetProc. See MSDN documentation. // // Returns 0 always. // { TRACE2( "UnHelpCallbackFunc(m=%d,l=%08x)",unMsg, lparam ); if (unMsg == PSCB_PRECREATE) { extern BOOL g_fNoWinHelp; // Turn off context help button if WinHelp won't work. See // common\uiutil\ui.c. // if (g_fNoWinHelp) { DLGTEMPLATE* pDlg = (DLGTEMPLATE* )lparam; pDlg->style &= ~(DS_CONTEXTHELP); } } return 0; }