|
|
//
// Random stuff
//
//
#include "priv.h"
#include "exdisp.h"
#include "mshtml.h"
#include "htiframe.h"
#include "util.h"
#include "resource.h"
#include "appwizid.h"
#define CPP_FUNCTIONS
#include <crtfree.h> // declare new, delete, etc.
#define DATEFORMAT_MAX 40
#include <shguidp.h>
#include <ieguidp.h>
// is this okay to do?
#ifdef ENTERCRITICAL
#undef ENTERCRITICAL
#endif
#ifdef LEAVECRITICAL
#undef LEAVECRITICAL
#endif
#define ENTERCRITICAL
#define LEAVECRITICAL
#include "..\inc\uassist.cpp"
// Prototype
BOOL _IsARPAllowed(void);
const VARIANT c_vaEmpty = {0}; #define PVAREMPTY ((VARIANT*)&c_vaEmpty)
STDAPI OpenAppMgr(HWND hwnd, int nPage) { HRESULT hres = E_FAIL;
// Make sure we aren't restricted
if (!_IsARPAllowed()) { ShellMessageBox(g_hinst, hwnd, MAKEINTRESOURCE(IDS_RESTRICTION), MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION); } else if ((nPage >= 0) && (nPage < NUMSTARTPAGES)) { ARP(hwnd, nPage); hres = S_OK; } return hres; }
inline void StrFree(LPWSTR psz) { if (psz) SHFree(psz); }
/*-------------------------------------------------------------------------
Purpose: Clear the given app data structure. Frees any allocated fields. */ void ClearAppInfoData(APPINFODATA * pdata) { if (pdata) { if (pdata->dwMask & AIM_DISPLAYNAME) StrFree(pdata->pszDisplayName); if (pdata->dwMask & AIM_VERSION) StrFree(pdata->pszVersion);
if (pdata->dwMask & AIM_PUBLISHER) StrFree(pdata->pszPublisher); if (pdata->dwMask & AIM_PRODUCTID) StrFree(pdata->pszProductID); if (pdata->dwMask & AIM_REGISTEREDOWNER) StrFree(pdata->pszRegisteredOwner); if (pdata->dwMask & AIM_REGISTEREDCOMPANY) StrFree(pdata->pszRegisteredCompany); if (pdata->dwMask & AIM_LANGUAGE) StrFree(pdata->pszLanguage); if (pdata->dwMask & AIM_SUPPORTURL) StrFree(pdata->pszSupportUrl); if (pdata->dwMask & AIM_SUPPORTTELEPHONE) StrFree(pdata->pszSupportTelephone); if (pdata->dwMask & AIM_HELPLINK) StrFree(pdata->pszHelpLink); if (pdata->dwMask & AIM_INSTALLLOCATION) StrFree(pdata->pszInstallLocation); if (pdata->dwMask & AIM_INSTALLSOURCE) StrFree(pdata->pszInstallSource); if (pdata->dwMask & AIM_INSTALLDATE) StrFree(pdata->pszInstallDate); if (pdata->dwMask & AIM_CONTACT) StrFree(pdata->pszContact);
if (pdata->dwMask & AIM_COMMENTS) StrFree(pdata->pszComments);
if (pdata->dwMask & AIM_IMAGE) StrFree(pdata->pszImage); } }
void ClearSlowAppInfo(SLOWAPPINFO * pdata) { if (pdata) { StrFree(pdata->pszImage); pdata->pszImage = NULL; } }
// NOTE: Returns TRUE only if psaiNew has valid info and different from psaiOrig
BOOL IsSlowAppInfoChanged(PSLOWAPPINFO psaiOrig, PSLOWAPPINFO psaiNew) { BOOL bRet = FALSE;
ASSERT(psaiOrig && psaiNew);
if (psaiNew) { // Compare size first
if (psaiOrig == NULL) { bRet = TRUE; } else if (((__int64)psaiNew->ullSize > 0) && (psaiNew->ullSize != psaiOrig->ullSize)) { bRet = TRUE; } // Now compare the file time
else if (((0 != psaiNew->ftLastUsed.dwHighDateTime) && (psaiOrig->ftLastUsed.dwHighDateTime != psaiNew->ftLastUsed.dwHighDateTime)) || ((0 != psaiNew->ftLastUsed.dwLowDateTime) && (psaiOrig->ftLastUsed.dwLowDateTime != psaiNew->ftLastUsed.dwLowDateTime))) { bRet = TRUE; } // Compare times used
else if (psaiOrig->iTimesUsed != psaiNew->iTimesUsed) { bRet = TRUE; } // Compare the icon image
else if ((psaiNew->pszImage != NULL) && (psaiOrig->pszImage != NULL) && lstrcmpi(psaiNew->pszImage, psaiOrig->pszImage)) bRet = TRUE;
} return bRet; }
void ClearManagedApplication(MANAGEDAPPLICATION * pma) { if (pma) { if (pma->pszPackageName) LocalFree(pma->pszPackageName);
if (pma->pszPublisher) LocalFree(pma->pszPublisher);
if (pma->pszPolicyName) LocalFree(pma->pszPolicyName);
if (pma->pszOwner) LocalFree(pma->pszOwner);
if (pma->pszCompany) LocalFree(pma->pszCompany);
if (pma->pszComments) LocalFree(pma->pszComments);
if (pma->pszContact) LocalFree(pma->pszContact); } }
/*-------------------------------------------------------------------------
Purpose: Clear the given PUBAPPINFO data structure. Frees any allocated fields. */ void ClearPubAppInfo(PUBAPPINFO * pdata) { if (pdata) { if ((pdata->dwMask & PAI_SOURCE) && pdata->pszSource) StrFree(pdata->pszSource); } }
/*-------------------------------------------------------------------------
Purpose: Frees a specific category structure */ HRESULT ReleaseShellCategory(SHELLAPPCATEGORY * psac) { ASSERT(psac);
if (psac->pszCategory) { SHFree(psac->pszCategory); psac->pszCategory = NULL; } return S_OK; }
/*-------------------------------------------------------------------------
Purpose: Frees the list of categories */ HRESULT ReleaseShellCategoryList(SHELLAPPCATEGORYLIST * psacl) { UINT i; SHELLAPPCATEGORY * psac;
ASSERT(psacl);
psac = psacl->pCategory; for (i = 0; i < psacl->cCategories; i++, psac++) { ReleaseShellCategory(psac); } return S_OK; }
#define MAX_INT64_SIZE 30 // 2^64 is less than 30 chars long
#define MAX_COMMA_NUMBER_SIZE (MAX_INT64_SIZE + 10)
#define MAX_COMMA_AS_K_SIZE (MAX_COMMA_NUMBER_SIZE + 10)
#define HIDWORD(_qw) (DWORD)((_qw)>>32)
#define LODWORD(_qw) (DWORD)(_qw)
void Int64ToStr( _int64 n, LPTSTR lpBuffer) { TCHAR szTemp[MAX_INT64_SIZE]; _int64 iChr;
iChr = 0;
do { szTemp[iChr++] = TEXT('0') + (TCHAR)(n % 10); n = n / 10; } while (n != 0);
do { iChr--; *lpBuffer++ = szTemp[iChr]; } while (iChr != 0);
*lpBuffer++ = '\0'; }
// takes a DWORD add commas etc to it and puts the result in the buffer
LPTSTR WINAPI AddCommas64(_int64 n, LPTSTR pszResult, UINT cchResult) { // FEATURE: We should pass in the lenght on pszResult buffer, we assume 40 will be enough
TCHAR szTemp[MAX_COMMA_NUMBER_SIZE]; TCHAR szSep[5]; NUMBERFMT nfmt;
nfmt.NumDigits=0; nfmt.LeadingZero=0; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep)); nfmt.Grouping = StrToInt(szSep); GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep)); nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep; nfmt.NegativeOrder= 0;
Int64ToStr(n, szTemp);
// Should have passed in size
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, MAX_COMMA_NUMBER_SIZE) == 0) { StringCchCopy(pszResult, cchResult, szTemp); }
return pszResult; }
//
// Add Peta 10^15 and Exa 10^18 to support 64-bit integers.
//
const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB, IDS_ORDERPB, IDS_ORDEREB};
/* converts numbers into sort formats
* 532 -> 523 bytes * 1340 -> 1.3KB * 23506 -> 23.5KB * -> 2.4MB * -> 5.2GB */ LPTSTR WINAPI ShortSizeFormat64(__int64 dw64, LPTSTR szBuf) { int i; _int64 wInt; UINT wLen, wDec; TCHAR szTemp[MAX_COMMA_NUMBER_SIZE], szOrder[20], szFormat[5];
if (dw64 < 1000) { StringCchPrintf(szTemp, ARRAYSIZE(szTemp), TEXT("%d"), LODWORD(dw64)); i = 0; goto AddOrder; }
for (i = 1; i<ARRAYSIZE(pwOrders)-1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++); /* do nothing */
wInt = dw64 >> 10; AddCommas64(wInt, szTemp, ARRAYSIZE(szTemp)); wLen = lstrlen(szTemp); if (wLen < 3) { wDec = LODWORD(dw64 - wInt * 1024L) * 1000 / 1024; // At this point, wDec should be between 0 and 1000
// we want get the top one (or two) digits.
wDec /= 10; if (wLen == 2) wDec /= 10;
// Note that we need to set the format before getting the
// intl char.
StringCchCopy(szFormat, ARRAYSIZE(szFormat), TEXT("%02d"));
szFormat[2] = TEXT('0') + 3 - wLen; GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szTemp+wLen, ARRAYSIZE(szTemp)-wLen); wLen = lstrlen(szTemp); wLen += wsprintf(szTemp+wLen, szFormat, wDec); }
AddOrder: LoadString(HINST_THISDLL, pwOrders[i], szOrder, ARRAYSIZE(szOrder)); StringCchPrintf(szBuf, ARRAYSIZE(szBuf), szOrder, (LPTSTR)szTemp);
return szBuf; }
#define c_szUninstallPolicy L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Uninstall"
/*-------------------------------------------------------------------------
Purpose: Helper function for ARP's policy check */ DWORD ARPGetRestricted(LPCWSTR pszPolicy) { return SHGetRestriction(NULL, TEXT("Uninstall"), pszPolicy); }
/*-------------------------------------------------------------------------
Purpose: Return a policy string value */ void ARPGetPolicyString(LPCWSTR pszPolicy, LPWSTR pszBuf, int cch) { DWORD dwSize, dwType;
*pszBuf = 0; // Check local machine first and let it override what the
// HKCU policy has done.
dwSize = cch * sizeof(WCHAR); if (ERROR_SUCCESS != SHGetValueW(HKEY_LOCAL_MACHINE, c_szUninstallPolicy, pszPolicy, &dwType, pszBuf, &dwSize)) { // Check current user if we didn't find anything for the local machine.
dwSize = cch * sizeof(WCHAR); SHGetValueW(HKEY_CURRENT_USER, c_szUninstallPolicy, pszPolicy, &dwType, pszBuf, &dwSize); } }
/*-------------------------------------------------------------------------
Purpose: Returns TRUE if it's okay to start ARP.
*/ BOOL _IsARPAllowed(void) { // ARP is forbidden if the entire CPL is disabled
if (ARPGetRestricted(L"NoAddRemovePrograms")) { return FALSE; }
// ARP is permitted if there exists a non-restricted page.
BOOL fAnyPages = !ARPGetRestricted(L"NoRemovePage") || !ARPGetRestricted(L"NoAddPage") || !ARPGetRestricted(L"NoWindowsSetupPage");
// If we are not a server SKU, then also check the new page.
if (!fAnyPages && !IsOS(OS_ANYSERVER)) { fAnyPages = !ARPGetRestricted(L"NoChooseProgramsPage"); }
return fAnyPages; }
/*-------------------------------------------------------------------------
Purpose: Take the error message and give user feedback through messagebox */ void _ARPErrorMessageBox(DWORD dwError) { TCHAR szErrorMsg[MAX_PATH]; szErrorMsg[0] = 0;
LPTSTR pszMsg = NULL; switch (dwError) { // The following error code cases are ignored.
case ERROR_INSTALL_USEREXIT: case ERROR_SUCCESS_REBOOT_REQUIRED: case ERROR_SUCCESS_REBOOT_INITIATED: ASSERT(pszMsg == NULL); break;
default: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0L, szErrorMsg, ARRAYSIZE(szErrorMsg), NULL); pszMsg = szErrorMsg; break; }
if (pszMsg) { ShellMessageBox( g_hinst, NULL, pszMsg, MAKEINTRESOURCE( IDS_NAME ), MB_OK | MB_ICONEXCLAMATION); } }
/*-------------------------------------------------------------------------
Purpose: Format the SYSTEMTIME into the following format: "mm/dd/yy h:mm" */ BOOL FormatSystemTimeString(LPSYSTEMTIME pst, LPTSTR pszStr, UINT cchStr) { BOOL bRet = FALSE; FILETIME ft = {0};
if (SystemTimeToFileTime(pst, &ft)) { DWORD dwFlags = FDTF_SHORTTIME | FDTF_SHORTDATE; bRet = SHFormatDateTime(&ft, &dwFlags, pszStr, cchStr); } return bRet; }
/*-------------------------------------------------------------------------
Purpose: Get the correct Date time format for specific locale */ BOOL _GetLocaleDateTimeFormat(LPTSTR pszFormat, UINT cchFormat) { TCHAR szTime[DATEFORMAT_MAX]; TCHAR szDate[DATEFORMAT_MAX]; if (cchFormat >= (ARRAYSIZE(szTime) + ARRAYSIZE(szDate) + 2)) { LCID lcid = LOCALE_USER_DEFAULT; if (GetLocaleInfo(lcid, LOCALE_STIMEFORMAT, szTime, ARRAYSIZE(szTime)) && GetLocaleInfo(lcid, LOCALE_SSHORTDATE, szDate, ARRAYSIZE(szDate))) { StringCchPrintf(pszFormat, cchFormat, TEXT("%s %s"), szDate, szTime); return TRUE; } }
return FALSE; }
/*-------------------------------------------------------------------------
Purpose: Compare two SYSTEMTIME data
Returnes : 1 : st1 > st2 0 : st1 == st2 -1: st1 < st2
NOTE: We do not compare seconds since ARP does not need that much precision. */ int CompareSystemTime(SYSTEMTIME *pst1, SYSTEMTIME *pst2) { int iRet;
if (pst1->wYear < pst2->wYear) iRet = -1; else if (pst1->wYear > pst2->wYear) iRet = 1; else if (pst1->wMonth < pst2->wMonth) iRet = -1; else if (pst1->wMonth > pst2->wMonth) iRet = 1; else if (pst1->wDay < pst2->wDay) iRet = -1; else if (pst1->wDay > pst2->wDay) iRet = 1; else if (pst1->wHour < pst2->wHour) iRet = -1; else if (pst1->wHour > pst2->wHour) iRet = 1; else if (pst1->wMinute < pst2->wMinute) iRet = -1; else if (pst1->wMinute > pst2->wMinute) iRet = 1; // else if (pst1->wSecond < pst2->wSecond)
// iRet = -1;
// else if (pst1->wSecond > pst2->wSecond)
// iRet = 1;
else iRet = 0;
return(iRet); }
/*--------------------------------------------------------------------------
Purpose: Window proc for the add later dialog box */ BOOL_PTR CALLBACK AddLaterDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_INITDIALOG: { PADDLATERDATA pald = (PADDLATERDATA)lp;
// We should definitely have this (dli)
ASSERT(pald);
SYSTEMTIME stInit = {0}; // Get the current local time
GetLocalTime(&stInit);
// Has this app already expired?
if ((pald->dwMasks & ALD_EXPIRE) && (CompareSystemTime(&pald->stExpire, &stInit) > 0)) { // NO,
// Assigned time does not make sense if the assigned time has already
// passed
if ((pald->dwMasks & ALD_ASSIGNED) && (CompareSystemTime(&pald->stAssigned, &stInit) <= 0)) pald->dwMasks &= ~ALD_ASSIGNED;
// find the date/time picker window
HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER);
// always check "add later" radio button initially
CheckDlgButton(hDlg, IDC_ADDLATER, BST_CHECKED);
TCHAR szFormat[MAX_PATH]; if (_GetLocaleDateTimeFormat(szFormat, ARRAYSIZE(szFormat))) { // set the locale date time format
DateTime_SetFormat(hwndPicker, szFormat);
// The new time can only be in the future, so set the current time
// as the lower limit
DateTime_SetRange(hwndPicker, GDTR_MIN, &stInit);
// Do we have a schedule (in the future) already?
// Schedule in the past means nothing
if ((pald->dwMasks & ALD_SCHEDULE) && (CompareSystemTime(&pald->stSchedule, &stInit) >= 0)) { // Set our initial value to this schedule
stInit = pald->stSchedule; }
// Set the initial value in date/time picker
DateTime_SetSystemtime(hwndPicker, GDT_VALID, &stInit);
// Uncheck the SCHEDULE flag so that we know we don't have a new
// schedule, yet
pald->dwMasks &= ~ALD_SCHEDULE;
SetWindowLongPtr(hDlg, DWLP_USER, lp);
return TRUE; } } else { // Yes, it's expired, warn the user
ShellMessageBox(g_hinst, hDlg, MAKEINTRESOURCE(IDS_EXPIRED), MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
// Then end the dialog.
EndDialog(hDlg, 0); } return FALSE; } break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wp, lp)) { case IDC_ADDLATER: case IDC_UNSCHEDULE: { HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER); EnableWindow(hwndPicker, IsDlgButtonChecked(hDlg, IDC_ADDLATER)); } break; case IDOK: { PADDLATERDATA pald = (PADDLATERDATA)GetWindowLongPtr(hDlg, DWLP_USER);
// we did set window long ptr this should be there.
ASSERT(pald);
// did the user choose to add later?
if (IsDlgButtonChecked(hDlg, IDC_ADDLATER)) { // Yes
// Let's find out if the time user has chosen is valid
#define LATER_THAN_ASSIGNED_TIME 1
#define LATER_THAN_EXPIRED_TIME 2
int iStatus = 0; HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER); DateTime_GetSystemtime(hwndPicker, &pald->stSchedule);
// Is this time later than the assigned time?
if ((pald->dwMasks & ALD_ASSIGNED) && (CompareSystemTime(&pald->stSchedule, &pald->stAssigned) > 0)) iStatus = LATER_THAN_ASSIGNED_TIME;
// Is this time later than the expired time?
if ((pald->dwMasks & ALD_EXPIRE) && (CompareSystemTime(&pald->stSchedule, &pald->stExpire) >= 0)) iStatus = LATER_THAN_EXPIRED_TIME;
// Is either of the above two cases TRUE?
if (iStatus > 0) { TCHAR szDateTime[MAX_PATH]; // Is the time user chose passed expired time or assigned?
BOOL bExpired = (iStatus == LATER_THAN_EXPIRED_TIME); // Get the time string
if (FormatSystemTimeString(bExpired ? &pald->stExpire : &pald->stAssigned, szDateTime, ARRAYSIZE(szDateTime))) { TCHAR szFinal[MAX_PATH * 2]; TCHAR szWarn[MAX_PATH]; LoadString(g_hinst, bExpired ? IDS_PASSEXPIRED : IDS_PASSASSIGNED, szWarn, ARRAYSIZE(szWarn)); StringCchPrintf(szFinal, ARRAYSIZE(szFinal), szWarn, szDateTime, szDateTime); ShellMessageBox(g_hinst, hDlg, szFinal, MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION); } } else // No, we are okay to go
pald->dwMasks |= ALD_SCHEDULE; } }
//
// fall through
//
case IDCANCEL: EndDialog(hDlg, (GET_WM_COMMAND_ID(wp, lp) == IDOK)); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
/*-------------------------------------------------------------------------
Purpose: GetNewInstallTime
Start up the Add Later dialog box to get the new install schedule (represented by a SYSTEMTIME data struct) */ BOOL GetNewInstallTime(HWND hwndParent, PADDLATERDATA pal) { return (DialogBoxParam(g_hinst, MAKEINTRESOURCE(DLG_ADDLATER), hwndParent, AddLaterDlgProc, (LPARAM)pal) == IDOK); }
// Take the name of the potential app folder and see if it ends with numbers or dots
// if it does, let's separate the numbers and see if there is a match.
// It's inspired by cases like Office8.0 or MSVC50 or Bookshelf98
// NOTE: we can't use the key words without the numbers, it might lead to mistake
// in case the user has two versions of the same software on one machine. (there might
// be something we can do though, I am too tired to think about this now)
void InsertSpaceBeforeVersion(LPCTSTR pszIn, LPTSTR pszOut) { ASSERT(IS_VALID_STRING_PTR(pszIn, -1)); ASSERT(IS_VALID_STRING_PTR(pszOut, -1));
// Copy the old string into the buffer
lstrcpy(pszOut, pszIn);
// Find the end of the string
LPTSTR pszEnd = pszOut + lstrlen(pszOut); ASSERT(pszEnd > pszOut);
// Go back until we can't see numbers or '.'
LPTSTR pszLastChar = CharPrev(pszOut, pszEnd); LPTSTR pszPrev = pszLastChar; while ((pszPrev > pszOut) && (((*pszPrev <= TEXT('9')) && (*pszPrev >= TEXT('0'))) || (*pszPrev == TEXT('.')))) pszPrev = CharPrev(pszOut, pszPrev);
// Did we find any numbers at the end?
if ((pszPrev < pszLastChar) && IsCharAlphaNumeric(*pszPrev)) { // Yes, let's stick a ' ' in between
TCHAR szNumbers[MAX_PATH]; StringCchCopy(szNumbers, ARRAYSIZE(szNumbers), ++pszPrev); *(pszPrev++) = TEXT(' '); lstrcpy(pszPrev, szNumbers); } }
//
// Basic sanity check on whether the app folder location is valid.
// Return Value:
// TRUE does not mean it is valid.
// FALSE means it definitely is not valid.
//
BOOL IsValidAppFolderLocation(LPCTSTR pszFolder) { ASSERT(IS_VALID_STRING_PTR(pszFolder, -1)); BOOL bRet = FALSE; if (!PathIsRoot(pszFolder) && PathFileExists(pszFolder) && PathIsDirectory(pszFolder)) { TCHAR szPath[MAX_PATH]; if (SUCCEEDED(StringCchCopy(szPath, ARRAYSIZE(szPath), pszFolder)) && PathStripToRoot(szPath)) { bRet = (GetDriveType(szPath) == DRIVE_FIXED); } }
return bRet; }
EXTERN_C BOOL IsTerminalServicesRunning(void) { static int s_fIsTerminalServer = -1;
if (s_fIsTerminalServer == -1) { BOOL TSAppServer; BOOL TSRemoteAdmin; OSVERSIONINFOEX osVersionInfo; DWORDLONG dwlConditionMask = 0; ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX)); osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL; VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND ); TSAppServer = (int)VerifyVersionInfo(&osVersionInfo, VER_SUITENAME, dwlConditionMask); ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX)); osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); osVersionInfo.wSuiteMask = VER_SUITE_SINGLEUSERTS; VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND ); TSRemoteAdmin = (int)VerifyVersionInfo(&osVersionInfo, VER_SUITENAME, dwlConditionMask); if ( !TSRemoteAdmin && TSAppServer ) { s_fIsTerminalServer = TRUE; } else { // do not treat tsremoteadmin as TS machine from the application compatability point of view.
s_fIsTerminalServer = FALSE; } }
return s_fIsTerminalServer ? TRUE : FALSE; }
// returns TRUE if pszFile is a local file and on a fixed drive
BOOL PathIsLocalAndFixed(LPCTSTR pszFile) { if (!pszFile || !pszFile[0]) return FALSE;
if (PathIsUNC(pszFile)) return FALSE; TCHAR szDrive[MAX_PATH]; StringCchCopy(szDrive, ARRAYSIZE(szDrive), pszFile); if (PathStripToRoot(szDrive) && GetDriveType(szDrive) != DRIVE_FIXED) return FALSE;
return TRUE; }
// This function will duplicate an APPCATEGORYINFOLIST and allocate the new copy
// using COM memory allocation functions
STDAPI _DuplicateCategoryList(APPCATEGORYINFOLIST * pacl, APPCATEGORYINFOLIST * paclNew) { HRESULT hres = E_FAIL; ASSERT(pacl && paclNew); ZeroMemory(paclNew, SIZEOF(APPCATEGORYINFOLIST));
if (pacl && (pacl->cCategory > 0) && pacl->pCategoryInfo) { DWORD dwDesiredSize = pacl->cCategory * SIZEOF(APPCATEGORYINFO); APPCATEGORYINFO * paci = pacl->pCategoryInfo; paclNew->pCategoryInfo = (APPCATEGORYINFO *)SHAlloc(dwDesiredSize); if (paclNew->pCategoryInfo) { UINT iCategory = 0; paclNew->cCategory = 0; APPCATEGORYINFO * paciNew = paclNew->pCategoryInfo; while (paci && (iCategory < pacl->cCategory)) { if (paci->pszDescription) { hmemcpy(paciNew, paci, SIZEOF(APPCATEGORYINFO)); if (FAILED(SHStrDup(paci->pszDescription, &(paciNew->pszDescription)))) { // We may be out of memory, stop here.
ZeroMemory(paciNew, SIZEOF(APPCATEGORYINFO)); break; } paciNew++; paclNew->cCategory++; } iCategory++; paci++; }
hres = S_OK; } else hres = E_OUTOFMEMORY; } return hres; }
STDAPI _DestroyCategoryList(APPCATEGORYINFOLIST * pacl) { if (pacl && pacl->pCategoryInfo) { UINT iCategory = 0; APPCATEGORYINFO * paci = pacl->pCategoryInfo; while (paci && (iCategory < pacl->cCategory)) { if (paci->pszDescription) { SHFree(paci->pszDescription); } iCategory++; paci++; } SHFree(pacl->pCategoryInfo); }
return S_OK; }
|