//--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- #include "grpconv.h" #include "util.h" #include "rcids.h" //--------------------------------------------------------------------------- // Global to this file only. const TCHAR g_szDot[] = TEXT("."); const TCHAR g_szShellOpenCommand[] = TEXT("\\Shell\\Open\\Command"); const TCHAR c_szElipses[] = TEXT("..."); const TCHAR c_szSpace[] = TEXT(" "); const TCHAR c_szUS[] = TEXT("_"); static BOOL g_fShowProgressDlg = FALSE; HWND g_hwndProgress = NULL; // Progress dialog. //--------------------------------------------------------------------------- LRESULT CALLBACK ProgressWndProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_INITDIALOG: SetDlgItemText(hdlg, IDC_GROUPNAME, (LPTSTR)lparam); EnableMenuItem(GetSystemMenu(hdlg, FALSE), SC_CLOSE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); return TRUE; } return 0; } //--------------------------------------------------------------------------- void ShowProgressDlg(void) { // Has someone tried to create the dialog but it isn't up yet? if (g_fShowUI && g_fShowProgressDlg && !g_hwndProgress) { // Yep. // NB We can handle this failing, we just try to carry on without // the dialog. g_hwndProgress = CreateDialog(g_hinst, MAKEINTRESOURCE(DLG_PROGRESS), NULL, ProgressWndProc); } } //--------------------------------------------------------------------------- void Group_CreateProgressDlg(void) { // NB We just set a flag here, the first guy to try to set the // current progress actually puts up the dialag. g_fShowProgressDlg = TRUE; } //--------------------------------------------------------------------------- void Group_DestroyProgressDlg(void) { if (g_hwndProgress) { DestroyWindow(g_hwndProgress); g_hwndProgress = NULL; } g_fShowProgressDlg = FALSE; } //--------------------------------------------------------------------------- // If the text is too long, lop off the end and stick on some elipses. void Text_TruncateAndAddElipses(HWND hwnd, LPTSTR lpszText) { RECT rcClient; SIZE sizeText; SIZE sizeElipses; HDC hdc; UINT cch; Assert(hwnd); Assert(lpszText); hdc = GetDC(hwnd); if (hdc) { GetClientRect(hwnd, &rcClient); GetTextExtentPoint(hdc, lpszText, lstrlen(lpszText), &sizeText); // Is the text too long? if (sizeText.cx > rcClient.right) { // Yes, it is, clip it. GetTextExtentPoint(hdc, c_szElipses, 3, &sizeElipses); GetTextExtentExPoint(hdc, lpszText, lstrlen(lpszText), rcClient.right - sizeElipses.cx, &cch, NULL, &sizeText); lstrcpy(lpszText+cch, c_szElipses); } ReleaseDC(hwnd, hdc); } } //--------------------------------------------------------------------------- void Group_SetProgressDesc(UINT nID) { TCHAR sz[MAX_PATH]; ShowProgressDlg(); if (g_hwndProgress) { LoadString(g_hinst, nID, sz, ARRAYSIZE(sz)); SendDlgItemMessage(g_hwndProgress, IDC_STATIC, WM_SETTEXT, 0, (LPARAM)sz); } } //--------------------------------------------------------------------------- void Group_SetProgressNameAndRange(LPCTSTR lpszGroup, int iMax) { TCHAR sz[MAX_PATH]; TCHAR szNew[MAX_PATH]; LPTSTR lpszName; MSG msg; static int cGen = 1; ShowProgressDlg(); if (g_hwndProgress) { // DebugMsg(DM_TRACE, "gc.gspnar: Range 0 to %d", iMax); SendDlgItemMessage(g_hwndProgress, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, iMax)); if (lpszGroup == (LPTSTR)-1) { // Use some sensible name - Programs (x) // where x = 1 to n, incremented each time this is // called. LoadString(g_hinst, IDS_GROUP, sz, ARRAYSIZE(sz)); wsprintf(szNew, TEXT("%s (%d)"), sz, cGen++); SetDlgItemText(g_hwndProgress, IDC_GROUPNAME, szNew); } else if (lpszGroup && *lpszGroup) { lpszName = PathFindFileName(lpszGroup); lstrcpy(sz, lpszName); Text_TruncateAndAddElipses(GetDlgItem(g_hwndProgress, IDC_GROUPNAME), sz); SetDlgItemText(g_hwndProgress, IDC_GROUPNAME, sz); } else { // Use some sensible name. LoadString(g_hinst, IDS_PROGRAMS, sz, ARRAYSIZE(sz)); SetDlgItemText(g_hwndProgress, IDC_GROUPNAME, sz); } // Let paints come in. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { DispatchMessage(&msg); } } } //--------------------------------------------------------------------------- void Group_SetProgress(int i) { MSG msg; ShowProgressDlg(); if (g_hwndProgress) { // DebugMsg(DM_TRACE, "gc.gsp: Progress %d", i); // Progman keeps trying to steal the focus... SetForegroundWindow(g_hwndProgress); SendDlgItemMessage(g_hwndProgress, IDC_PROGRESS, PBM_SETPOS, i, 0); } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { DispatchMessage(&msg); } } #if 0 //--------------------------------------------------------------------------- BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszValue, int i, LPCTSTR lpszIniFile) { TCHAR szBuf[CCHSZSHORT]; wsprintf(szBuf, TEXT("%d"), i); return WritePrivateProfileString(lpszSection, lpszValue, szBuf, lpszIniFile); } #endif //--------------------------------------------------------------------------- // Register an app as being able to handle a particular extension with the // given internal type, human readble type and command. // NB lpszExt doesn't need a dot. // By default this won't overide something in the registration DB. // Setting fOveride to TRUE will cause existing entries in the DB // to be over written. void ShellRegisterApp(LPCTSTR lpszExt, LPCTSTR lpszTypeKey, LPCTSTR lpszTypeValue, LPCTSTR lpszCommand, BOOL fOveride) { TCHAR szKey[CCHSZNORMAL]; TCHAR szValue[CCHSZSHORT]; LONG lcb; LONG lStatus; // Deal with the mapping from extension to TypeKey. lstrcpy(szKey, g_szDot); lstrcat(szKey, lpszExt); lcb = SIZEOF(szValue); lStatus = RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &lcb); // Is the extension not registered or do we even care? if (lStatus != ERROR_SUCCESS || fOveride) { // No, so register it. lstrcpy(szValue, lpszTypeKey); if (RegSetValue(HKEY_CLASSES_ROOT, szKey, REG_SZ, lpszTypeKey, 0) == ERROR_SUCCESS) { // DebugMsg(DM_TRACE, "gc.sra: Extension registered."); } else { DebugMsg(DM_ERROR, TEXT("gc.sra: Error registering extension.")); } } // Deal with the mapping from TypeKey to TypeValue lcb = SIZEOF(szValue); lStatus = RegQueryValue(HKEY_CLASSES_ROOT, lpszTypeKey, szValue, &lcb); // Is the type not registered or do we even care? if (lStatus != ERROR_SUCCESS || fOveride) { // No, so register it. if (RegSetValue(HKEY_CLASSES_ROOT, lpszTypeKey, REG_SZ, lpszTypeValue, 0) == ERROR_SUCCESS) { // DebugMsg(DM_TRACE, "gc.sra: Type registered."); } else { DebugMsg(DM_ERROR, TEXT("gc.sra: Error registering type.")); } } // Deal with adding the open command. lstrcpy(szKey, lpszTypeKey); lstrcat(szKey, g_szShellOpenCommand); lcb = SIZEOF(szValue); lStatus = RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &lcb); // Is the command not registered or do we even care? if (lStatus != ERROR_SUCCESS || fOveride) { // No, so register it. if (RegSetValue(HKEY_CLASSES_ROOT, szKey, REG_SZ, lpszCommand, 0) == ERROR_SUCCESS) { // DebugMsg(DM_TRACE, "gc.sra: Command registered."); } else { DebugMsg(DM_ERROR, TEXT("gc.sra: Error registering command.")); } } } #if 0 //------------------------------------------------------------------------- // Do a unix(ish) gets(). This assumes bufferd i/o. // Reads cb-1 characters (the last one will be a NULL) or up to and including // the first NULL. LPTSTR fgets(LPTSTR sz, WORD cb, int fh) { UINT i; // Leave room for the NULL. cb--; for (i=0; ilpVtbl->CreateInstance(pcf, NULL, riid, ppv); pcf->lpVtbl->Release(pcf); } return hres; } //------------------------------------------------------------------------- LPTSTR _lstrcatn(LPTSTR lpszDest, LPCTSTR lpszSrc, UINT cbDest) { UINT i; i = lstrlen(lpszDest); lstrcpyn(lpszDest+i, lpszSrc, cbDest-i); return lpszDest; } //------------------------------------------------------------------------- // Simplified from shelldll. Keep sticking on numbers till the name is unique. BOOL WINAPI MakeUniqueName(LPTSTR pszNewName, UINT cbNewName, LPCTSTR pszOldName, UINT nStart, PFNISUNIQUE pfnIsUnique, UINT nUser, BOOL fLFN) { TCHAR szAddend[4]; int cbAddend; int i; // Is it already unique? if ((*pfnIsUnique)(pszOldName, nUser)) { lstrcpyn(pszNewName, pszOldName, cbNewName); return TRUE; } else { // NB Max is 100 identically names things but we should never // hit this as the max number of items in a progman group was 50. for (i=nStart; i<100; i++) { // Generate the addend. wsprintf(szAddend, TEXT("#%d"), i); cbAddend = lstrlen(szAddend); // Lotsa room? if ((UINT)(lstrlen(pszOldName)+cbAddend+1) > cbNewName) { // Nope. lstrcpyn(pszNewName, pszOldName, cbNewName); lstrcpy(pszNewName+(cbNewName-cbAddend), szAddend); } else { // Yep. lstrcpy(pszNewName, pszOldName); if (!fLFN) lstrcat(pszNewName, c_szSpace); lstrcat(pszNewName, szAddend); } // Is it unique? if ((*pfnIsUnique)(pszNewName, nUser)) { // Yep. return TRUE; } } } // Ooopsie. lstrcpyn(pszNewName, pszOldName, cbNewName); DebugMsg(DM_ERROR, TEXT("gp.mun: Unable to generate a unique name for %s."), pszOldName); return FALSE; } //------------------------------------------------------------------------- // Simplified from shell.dll (For LFN things only). BOOL WINAPI YetAnotherMakeUniqueName(LPTSTR pszNewName, UINT cbNewName, LPCTSTR pszOldName, PFNISUNIQUE pfnIsUnique, UINT n, BOOL fLFN) { BOOL fRet = FALSE; TCHAR szTemp[MAX_PATH]; // Is given name already unique? if ((*pfnIsUnique)(pszOldName, n)) { // Yep, lstrcpyn(pszNewName, pszOldName, cbNewName); } else { if (fLFN) { // Try "another". LoadString(g_hinst, IDS_ANOTHER, szTemp, ARRAYSIZE(szTemp)); _lstrcatn(szTemp, pszOldName, cbNewName); if (!(*pfnIsUnique)(szTemp, n)) { // Nope, use the old technique of sticking on numbers. return MakeUniqueName(pszNewName, cbNewName, pszOldName, 3, pfnIsUnique, n, FALSE); } else { // Yep. lstrcpyn(pszNewName, szTemp, cbNewName); } } else { // Just stick on numbers. return MakeUniqueName(pszNewName, cbNewName, pszOldName, 2, pfnIsUnique, n, TRUE); } } // Name is unique. return TRUE; } //---------------------------------------------------------------------------- // Sort of a registry equivalent of the profile API's. BOOL WINAPI Reg_Get(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, LPVOID pData, DWORD cbData) { HKEY hkeyNew; BOOL fRet = FALSE; DWORD dwType; if (!GetSystemMetrics(SM_CLEANBOOT) && (RegOpenKey(hkey, pszSubKey, &hkeyNew) == ERROR_SUCCESS)) { if (RegQueryValueEx(hkeyNew, (LPVOID)pszValue, 0, &dwType, pData, &cbData) == ERROR_SUCCESS) { fRet = TRUE; } RegCloseKey(hkeyNew); } return fRet; } //---------------------------------------------------------------------------- // Sort of a registry equivalent of the profile API's. BOOL WINAPI Reg_Set(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, DWORD dwType, LPVOID pData, DWORD cbData) { HKEY hkeyNew; BOOL fRet = FALSE; if (pszSubKey) { if (RegCreateKey(hkey, pszSubKey, &hkeyNew) == ERROR_SUCCESS) { if (RegSetValueEx(hkeyNew, pszValue, 0, dwType, pData, cbData) == ERROR_SUCCESS) { fRet = TRUE; } RegCloseKey(hkeyNew); } } else { if (RegSetValueEx(hkey, pszValue, 0, dwType, pData, cbData) == ERROR_SUCCESS) { fRet = TRUE; } } return fRet; } //---------------------------------------------------------------------------- BOOL WINAPI Reg_SetDWord(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, DWORD dw) { return Reg_Set(hkey, pszSubKey, pszValue, REG_DWORD, &dw, SIZEOF(dw)); } //---------------------------------------------------------------------------- BOOL WINAPI Reg_GetDWord(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, LPDWORD pdw) { return Reg_Get(hkey, pszSubKey, pszValue, pdw, SIZEOF(*pdw)); } //---------------------------------------------------------------------------- void __cdecl _Log(LPCTSTR pszMsg, ...) { TCHAR sz[2*MAX_PATH+40]; // Handles 2*largest path + slop for message va_list vaListMarker; va_start(vaListMarker, pszMsg); if (g_hkeyGrpConv) { wvsprintf(sz, pszMsg, vaListMarker); Reg_SetString(g_hkeyGrpConv, NULL, TEXT("Log"), sz); } }