//********************************************************************** // File name: desktop.cpp // // Desktop manipulation functions // // Functions: // // Copyright (c) 1992 - 1998 Microsoft Corporation. All rights reserved. //********************************************************************** #include "pre.h" #include "regstr.h" #include "inetreg.h" #include #include // latest platform SDK has this #define MAX_USER_NAME 255 #define REGSTR_PATH_SETUPKEY REGSTR_PATH_SETUP REGSTR_KEY_SETUP #define REGSTR_PATH_IEONDESKTOP REGSTR_PATH_IEXPLORER TEXT("\\AdvancedOptions\\BROWSE\\IEONDESKTOP") #define InternetConnectionWiz "Internet Connection Wizard" #define NOICWICON "NoICWIcon" static const TCHAR g_szRegPathWelcomeICW[] = TEXT("Welcome\\ICW"); static const TCHAR g_szAllUsers[] = TEXT("All Users"); static const TCHAR g_szConnectApp[] = TEXT("ICWCONN1.EXE"); static const TCHAR g_szConnectLink[] = TEXT("Connect to the Internet"); static const TCHAR g_szOEApp[] = TEXT("MSINM.EXE"); static const TCHAR g_szOELink[] = TEXT("Outlook Express"); static const TCHAR g_szRegPathICWSettings[] = TEXT("Software\\Microsoft\\Internet Connection Wizard"); static const TCHAR g_szRegValICWCompleted[] = TEXT("Completed"); static const TCHAR g_szRegValNoIcon[] = TEXT("NoIcon"); extern BOOL MyIsSmartStartEx(LPTSTR lpszConnectionName, DWORD dwBufLen); extern BOOL IsNT(); extern BOOL IsNT5(); void QuickCompleteSignup() { // Set the welcome state UpdateWelcomeRegSetting(TRUE); // Restore the desktop UndoDesktopChanges(g_hInstance); // Mark the ICW as being complete SetICWComplete(); } void UpdateWelcomeRegSetting ( BOOL bSetBit ) { HKEY hkey; HKEY hkeyCurVer; DWORD dwValue = bSetBit; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, // ...\Windows\CurrentVersion 0, KEY_ALL_ACCESS, &hkeyCurVer) == ERROR_SUCCESS) { DWORD dwDisposition; if (ERROR_SUCCESS == RegCreateKeyEx(hkeyCurVer, g_szRegPathWelcomeICW, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition)) { RegSetValueEx(hkey, TEXT("@"), 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)); RegCloseKey(hkey); } RegCloseKey(hkeyCurVer); } } BOOL GetCompletedBit( ) { HKEY hkey; DWORD dwValue; DWORD dwRet = ERROR_GEN_FAILURE; DWORD dwType = REG_DWORD; BOOL bBit = FALSE; if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegPathICWSettings, // ...Software\\Microsoft\\Internet Connection Wizard 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) { DWORD dwDataSize = sizeof (dwValue); if (ERROR_SUCCESS == RegQueryValueEx(hkey, g_szRegValICWCompleted, NULL, &dwType, (LPBYTE) &dwValue, &dwDataSize)) { bBit = (1 == dwValue); } RegCloseKey(hkey); } return bBit; } // shlwapi!StrCatBuff is not be available in Win95/NT without IE5. Not sure // if ICW has to run in these environment or not. // // return pszDestination. always NULL terminated. void MyStrCatBuff( LPTSTR pszDestination, // in/out. null terminated string LPCTSTR pszSource, // in. null terminated string int cchDestBuffSize // in. size of pzDestination in TCHAR ) { int nDestLen = lstrlen(pszDestination); int nRemainLen = cchDestBuffSize - nDestLen; if (nRemainLen > 1) { // has room in additional to '\0' lstrcpyn(&(pszDestination[nDestLen]), pszSource, nRemainLen); } } void GetDesktopDirectory(TCHAR* pszPath) { LPITEMIDLIST lpItemDList = NULL; IMalloc* pMalloc = NULL; HRESULT hr = E_FAIL; if(IsNT5()) // Bug 81444 in IE DB hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &lpItemDList); else if (IsNT()) hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &lpItemDList); else { TCHAR pszFolder[MAX_PATH]; *pszFolder = 0; HRESULT hRet = S_FALSE; HMODULE hmod = LoadLibrary(TEXT("shfolder.dll")); PFNSHGETFOLDERPATH pfn = NULL; if (hmod) { pfn = (PFNSHGETFOLDERPATH)GetProcAddress(hmod, "SHGetFolderPathA"); // or W if you are unicode if (pfn) { hRet = pfn(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, pszFolder); if (S_OK != hRet) hRet = pfn(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, pszFolder); if (S_OK == hRet) lstrcpy(pszPath ,pszFolder); } FreeLibrary(hmod); } if (S_OK != hRet) { FARPROC hShell32VersionProc = NULL; HMODULE hShell32Mod = (HMODULE)LoadLibrary(TEXT("shell32.dll")); if (hShell32Mod) hShell32VersionProc = GetProcAddress(hShell32Mod, "DllGetVersion"); if(hShell32VersionProc) { TCHAR szDir [MAX_PATH] = TEXT("\0"); //ok, we're not NT, but we may be multiuser windows. GetWindowsDirectory(szDir, MAX_PATH); if (szDir) { MyStrCatBuff(szDir, TEXT("\\"), MAX_PATH); MyStrCatBuff(szDir, g_szAllUsers, MAX_PATH); TCHAR szTemp [MAX_MESSAGE_LEN] = TEXT("\0"); LoadString(g_hInstance, IDS_DESKTOP, szTemp, MAX_MESSAGE_LEN); if (szTemp) { MyStrCatBuff(szDir, TEXT("\\"), MAX_PATH); MyStrCatBuff(szDir, szTemp, MAX_PATH); lstrcpy(pszPath ,szDir); } } } else hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &lpItemDList); } } if (SUCCEEDED(hr)) { SHGetPathFromIDList(lpItemDList, pszPath); if (SUCCEEDED(SHGetMalloc (&pMalloc))) { pMalloc->Free (lpItemDList); pMalloc->Release (); } } } void RemoveDesktopShortCut ( LPTSTR lpszShortcutName ) { TCHAR szShortcutPath[MAX_PATH] = TEXT("\0"); GetDesktopDirectory(szShortcutPath); if(szShortcutPath[0] != TEXT('\0')) { lstrcat(szShortcutPath, TEXT("\\")); lstrcat(szShortcutPath, lpszShortcutName); lstrcat(szShortcutPath, TEXT(".LNK")); DeleteFile(szShortcutPath); } } // This function will add a desktop shortcut void AddDesktopShortCut ( LPTSTR lpszAppName, LPTSTR lpszLinkName ) { TCHAR szConnectPath [MAX_PATH] = TEXT("\0"); TCHAR szAppPath [MAX_PATH] = TEXT("\0"); TCHAR szConnectLinkPath [MAX_PATH] = TEXT("\0"); // Path the where the Shortcut file will livE TCHAR szdrive [_MAX_DRIVE] = TEXT("\0"); TCHAR szdir [_MAX_DIR] = TEXT("\0"); TCHAR szfname [_MAX_FNAME] = TEXT("\0"); TCHAR szext [_MAX_EXT] = TEXT("\0"); TCHAR szRegPath [MAX_PATH] = TEXT("\0"); HRESULT hres = E_FAIL; IShellLink* psl = NULL; HKEY hkey = NULL; // first get the app path lstrcpy(szRegPath, REGSTR_PATH_APPPATHS); lstrcat(szRegPath, TEXT("\\")); lstrcat(szRegPath, lpszAppName); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, 0, IsNT5()? KEY_QUERY_VALUE : KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS) { DWORD dwTmp = sizeof(szConnectPath); DWORD dwType = 0; if(RegQueryValueEx(hkey, NULL, NULL, &dwType, (LPBYTE) szConnectPath, &dwTmp) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } RegQueryValueEx(hkey, TEXT("Path"), NULL, &dwType, (LPBYTE) szAppPath, &dwTmp); RegCloseKey(hkey); } else { return; } GetDesktopDirectory(szConnectLinkPath); if(szConnectLinkPath[0] != TEXT('\0')) { // Append on the connect EXE name lstrcat(szConnectLinkPath, TEXT("\\")); lstrcat(szConnectLinkPath, lpszAppName); // int nLastChar = lstrlen(szAppPath)-1; if ((nLastChar > 0) && (';' == szAppPath[nLastChar])) szAppPath[nLastChar] = 0; // Split the path, and the reassemble with the .LNK extension _tsplitpath( szConnectLinkPath, szdrive, szdir, szfname, szext ); _tmakepath(szConnectLinkPath, szdrive, szdir, lpszLinkName, TEXT(".LNK")); // Create an IShellLink object and get a pointer to the IShellLink // interface (returned from CoCreateInstance). hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); if (SUCCEEDED (hres)) { IPersistFile *ppf; // Query IShellLink for the IPersistFile interface for // saving the shortcut in persistent storage. hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf); if (SUCCEEDED (hres)) { WORD wsz [MAX_PATH]; // buffer for Unicode string do { // Set the path to the shortcut target. if (!SUCCEEDED(psl->SetPath (szConnectPath))) break; // Set the working dir to the shortcut target. if (!SUCCEEDED(psl->SetWorkingDirectory (szAppPath))) break; // Set the args. if (!SUCCEEDED(psl->SetArguments (SHORTCUTENTRY_CMD))) break; // Set the description of the shortcut. TCHAR szDescription[MAX_MESSAGE_LEN]; if (!LoadString(g_hInstance, IDS_SHORTCUT_DESC, szDescription, MAX_MESSAGE_LEN)) lstrcpy(szDescription, lpszLinkName); if (!SUCCEEDED(psl->SetDescription (szDescription))) break; // Ensure that the string consists of ANSI TCHARacters. #ifdef UNICODE lstrcpy(wsz, szConnectLinkPath); #else MultiByteToWideChar (CP_ACP, 0, szConnectLinkPath, -1, wsz, MAX_PATH); #endif // Save the shortcut via the IPersistFile::Save member function. if (!SUCCEEDED(ppf->Save (wsz, TRUE))) break; // Release the pointer to IPersistFile. ppf->Release (); break; } while (1); } // Release the pointer to IShellLink. psl->Release (); } } } // This function will apply the appropriate desktop changes based on the following // algorithm. This code below assumes that the machine is NOT internet capable. // If the machine was upgraded from a previous OS, then // Add the connect to the internet ICON // ELSE (clean install or OEM pre install) // Add the connect to the internet ICON // void DoDesktopChanges ( HINSTANCE hAppInst ) { TCHAR szAppName[MAX_PATH]; TCHAR szLinkName[MAX_PATH]; HKEY hkey; if (!LoadString(hAppInst, IDS_CONNECT_FNAME, szAppName, ARRAYSIZE(szAppName))) lstrcpy(szAppName, g_szConnectApp); if (!LoadString(hAppInst, IDS_CONNECT_DESKTOP_TITLE, szLinkName, ARRAYSIZE(szLinkName))) lstrcpy(szLinkName, g_szConnectLink); // We always add the connect shortcut AddDesktopShortCut(szAppName, szLinkName); // Set a registry value indicating that we messed with the desktop DWORD dwDisposition; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, ICWSETTINGSPATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition)) { DWORD dwDesktopChanged = 1; RegSetValueEx(hkey, ICWDESKTOPCHANGED, 0, REG_DWORD, (LPBYTE)&dwDesktopChanged, sizeof(DWORD)); RegCloseKey(hkey); } } // This undoes what DoDesktopChanges did void UndoDesktopChanges ( HINSTANCE hAppInst ) { TCHAR szConnectTotheInternetTitle[MAX_PATH]; HKEY hkey; // Verify that we really changed the desktop if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, ICWSETTINGSPATH, 0, KEY_ALL_ACCESS, &hkey)) { DWORD dwDesktopChanged = 0; DWORD dwTmp = sizeof(DWORD); DWORD dwType = 0; RegQueryValueEx(hkey, ICWDESKTOPCHANGED, NULL, &dwType, (LPBYTE)&dwDesktopChanged, &dwTmp); RegCloseKey(hkey); // Bail if the desktop was not changed by us if(!dwDesktopChanged) return; } // Always nuke the Connect to the internet icon if (!LoadString(hAppInst, IDS_CONNECT_DESKTOP_TITLE, szConnectTotheInternetTitle, ARRAYSIZE(szConnectTotheInternetTitle))) { lstrcpy(szConnectTotheInternetTitle, g_szConnectLink); } RemoveDesktopShortCut(szConnectTotheInternetTitle); } void UpdateDesktop ( HINSTANCE hAppInst ) { if(MyIsSmartStartEx(NULL, 0)) { // VYUNG NT5 bug See if IEAK wants to stop GETCONN icon creation //if (!SHGetRestriction(NULL, TEXT("Internet Connection Wizard"), TEXT("NoICWIcon"))) // CHUNHOC NT5.1 bug Don't create icon at desktop in any case. /* if (!SHGetRestriction(NULL, L"Internet Connection Wizard", L"NoICWIcon")) DoDesktopChanges(hAppInst); */ } else { // We are internet ready, so set the appropriate Welcome show bit // and replace the IE and OE links UpdateWelcomeRegSetting(TRUE); } }