Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

931 lines
27 KiB

  1. //
  2. // Random stuff
  3. //
  4. //
  5. #include "priv.h"
  6. #include "exdisp.h"
  7. #include "mshtml.h"
  8. #include "htiframe.h"
  9. #include "util.h"
  10. #include "resource.h"
  11. #include "appwizid.h"
  12. #ifdef DOWNLEVEL_PLATFORM
  13. #define DF_DEBUGQI 0
  14. #define TF_QISTUB 0
  15. #ifdef DEBUG
  16. #define DEBUG_WAS_DEFINED
  17. #undef DEBUG
  18. #endif
  19. #include "dbutil.h"
  20. #include "..\inc\dbutil.cpp"
  21. #include "..\inc\qistub.cpp"
  22. #ifdef DEBUG_WAS_DEFINED
  23. #define DEBUG
  24. #undef DEBUG_WAS_DEFINED
  25. #endif
  26. #endif
  27. #define CPP_FUNCTIONS
  28. #include <crtfree.h> // declare new, delete, etc.
  29. #define DATEFORMAT_MAX 40
  30. #ifndef DOWNLEVEL_PLATFORM
  31. #include <shguidp.h>
  32. #include <ieguidp.h>
  33. // is this okay to do?
  34. #ifdef ENTERCRITICAL
  35. #undef ENTERCRITICAL
  36. #endif
  37. #ifdef LEAVECRITICAL
  38. #undef LEAVECRITICAL
  39. #endif
  40. #define ENTERCRITICAL
  41. #define LEAVECRITICAL
  42. #include "..\inc\uassist.cpp"
  43. #endif //DOWNLEVEL_PLATFORM
  44. // Prototype
  45. BOOL _IsARPAllowed(void);
  46. const VARIANT c_vaEmpty = {0};
  47. #define PVAREMPTY ((VARIANT*)&c_vaEmpty)
  48. STDAPI OpenAppMgr(HWND hwnd, int nPage)
  49. {
  50. HRESULT hres = E_FAIL;
  51. // Make sure we aren't restricted
  52. if (!_IsARPAllowed())
  53. {
  54. ShellMessageBox(g_hinst, hwnd, MAKEINTRESOURCE(IDS_RESTRICTION),
  55. MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
  56. }
  57. else if ((nPage >= 0) && (nPage < NUMSTARTPAGES))
  58. {
  59. ARP(hwnd, nPage);
  60. hres = S_OK;
  61. }
  62. return hres;
  63. }
  64. inline void StrFree(LPWSTR psz)
  65. {
  66. if (psz)
  67. SHFree(psz);
  68. }
  69. /*-------------------------------------------------------------------------
  70. Purpose: Clear the given app data structure. Frees any allocated fields.
  71. */
  72. void ClearAppInfoData(APPINFODATA * pdata)
  73. {
  74. if (pdata)
  75. {
  76. if (pdata->dwMask & AIM_DISPLAYNAME)
  77. StrFree(pdata->pszDisplayName);
  78. if (pdata->dwMask & AIM_VERSION)
  79. StrFree(pdata->pszVersion);
  80. if (pdata->dwMask & AIM_PUBLISHER)
  81. StrFree(pdata->pszPublisher);
  82. if (pdata->dwMask & AIM_PRODUCTID)
  83. StrFree(pdata->pszProductID);
  84. if (pdata->dwMask & AIM_REGISTEREDOWNER)
  85. StrFree(pdata->pszRegisteredOwner);
  86. if (pdata->dwMask & AIM_REGISTEREDCOMPANY)
  87. StrFree(pdata->pszRegisteredCompany);
  88. if (pdata->dwMask & AIM_LANGUAGE)
  89. StrFree(pdata->pszLanguage);
  90. if (pdata->dwMask & AIM_SUPPORTURL)
  91. StrFree(pdata->pszSupportUrl);
  92. if (pdata->dwMask & AIM_SUPPORTTELEPHONE)
  93. StrFree(pdata->pszSupportTelephone);
  94. if (pdata->dwMask & AIM_HELPLINK)
  95. StrFree(pdata->pszHelpLink);
  96. if (pdata->dwMask & AIM_INSTALLLOCATION)
  97. StrFree(pdata->pszInstallLocation);
  98. if (pdata->dwMask & AIM_INSTALLSOURCE)
  99. StrFree(pdata->pszInstallSource);
  100. if (pdata->dwMask & AIM_INSTALLDATE)
  101. StrFree(pdata->pszInstallDate);
  102. if (pdata->dwMask & AIM_CONTACT)
  103. StrFree(pdata->pszContact);
  104. if (pdata->dwMask & AIM_COMMENTS)
  105. StrFree(pdata->pszComments);
  106. if (pdata->dwMask & AIM_IMAGE)
  107. StrFree(pdata->pszImage);
  108. }
  109. }
  110. void ClearSlowAppInfo(SLOWAPPINFO * pdata)
  111. {
  112. if (pdata)
  113. {
  114. StrFree(pdata->pszImage);
  115. pdata->pszImage = NULL;
  116. }
  117. }
  118. // NOTE: Returns TRUE only if psaiNew has valid info and different from psaiOrig
  119. BOOL IsSlowAppInfoChanged(PSLOWAPPINFO psaiOrig, PSLOWAPPINFO psaiNew)
  120. {
  121. BOOL bRet = FALSE;
  122. ASSERT(psaiOrig && psaiNew);
  123. if (psaiNew)
  124. {
  125. // Compare size first
  126. if (psaiOrig == NULL)
  127. {
  128. bRet = TRUE;
  129. }
  130. else if (((__int64)psaiNew->ullSize > 0) && (psaiNew->ullSize != psaiOrig->ullSize))
  131. {
  132. bRet = TRUE;
  133. }
  134. // Now compare the file time
  135. else if (((0 != psaiNew->ftLastUsed.dwHighDateTime) &&
  136. (psaiOrig->ftLastUsed.dwHighDateTime != psaiNew->ftLastUsed.dwHighDateTime))
  137. || ((0 != psaiNew->ftLastUsed.dwLowDateTime) &&
  138. (psaiOrig->ftLastUsed.dwLowDateTime != psaiNew->ftLastUsed.dwLowDateTime)))
  139. {
  140. bRet = TRUE;
  141. }
  142. // Compare times used
  143. else if (psaiOrig->iTimesUsed != psaiNew->iTimesUsed)
  144. {
  145. bRet = TRUE;
  146. }
  147. // Compare the icon image
  148. else if ((psaiNew->pszImage != NULL) && (psaiOrig->pszImage != NULL) && lstrcmpi(psaiNew->pszImage, psaiOrig->pszImage))
  149. bRet = TRUE;
  150. }
  151. return bRet;
  152. }
  153. void ClearManagedApplication(MANAGEDAPPLICATION * pma)
  154. {
  155. if (pma)
  156. {
  157. if (pma->pszPackageName)
  158. LocalFree(pma->pszPackageName);
  159. if (pma->pszPublisher)
  160. LocalFree(pma->pszPublisher);
  161. if (pma->pszPolicyName)
  162. LocalFree(pma->pszPolicyName);
  163. if (pma->pszOwner)
  164. LocalFree(pma->pszOwner);
  165. if (pma->pszCompany)
  166. LocalFree(pma->pszCompany);
  167. if (pma->pszComments)
  168. LocalFree(pma->pszComments);
  169. if (pma->pszContact)
  170. LocalFree(pma->pszContact);
  171. }
  172. }
  173. /*-------------------------------------------------------------------------
  174. Purpose: Clear the given PUBAPPINFO data structure. Frees any allocated fields.
  175. */
  176. void ClearPubAppInfo(PUBAPPINFO * pdata)
  177. {
  178. if (pdata)
  179. {
  180. if ((pdata->dwMask & PAI_SOURCE) && pdata->pszSource)
  181. StrFree(pdata->pszSource);
  182. }
  183. }
  184. /*-------------------------------------------------------------------------
  185. Purpose: Frees a specific category structure
  186. */
  187. HRESULT ReleaseShellCategory(SHELLAPPCATEGORY * psac)
  188. {
  189. ASSERT(psac);
  190. if (psac->pszCategory)
  191. {
  192. SHFree(psac->pszCategory);
  193. psac->pszCategory = NULL;
  194. }
  195. return S_OK;
  196. }
  197. /*-------------------------------------------------------------------------
  198. Purpose: Frees the list of categories
  199. */
  200. HRESULT ReleaseShellCategoryList(SHELLAPPCATEGORYLIST * psacl)
  201. {
  202. UINT i;
  203. SHELLAPPCATEGORY * psac;
  204. ASSERT(psacl);
  205. psac = psacl->pCategory;
  206. for (i = 0; i < psacl->cCategories; i++, psac++)
  207. {
  208. ReleaseShellCategory(psac);
  209. }
  210. return S_OK;
  211. }
  212. #define MAX_INT64_SIZE 30 // 2^64 is less than 30 chars long
  213. #define MAX_COMMA_NUMBER_SIZE (MAX_INT64_SIZE + 10)
  214. #define MAX_COMMA_AS_K_SIZE (MAX_COMMA_NUMBER_SIZE + 10)
  215. #define HIDWORD(_qw) (DWORD)((_qw)>>32)
  216. #define LODWORD(_qw) (DWORD)(_qw)
  217. void Int64ToStr( _int64 n, LPTSTR lpBuffer)
  218. {
  219. TCHAR szTemp[MAX_INT64_SIZE];
  220. _int64 iChr;
  221. iChr = 0;
  222. do {
  223. szTemp[iChr++] = TEXT('0') + (TCHAR)(n % 10);
  224. n = n / 10;
  225. } while (n != 0);
  226. do {
  227. iChr--;
  228. *lpBuffer++ = szTemp[iChr];
  229. } while (iChr != 0);
  230. *lpBuffer++ = '\0';
  231. }
  232. // takes a DWORD add commas etc to it and puts the result in the buffer
  233. LPTSTR WINAPI AddCommas64(_int64 n, LPTSTR pszResult)
  234. {
  235. // FEATURE: We should pass in the lenght on pszResult buffer, we assume 40 will be enough
  236. TCHAR szTemp[MAX_COMMA_NUMBER_SIZE];
  237. TCHAR szSep[5];
  238. NUMBERFMT nfmt;
  239. nfmt.NumDigits=0;
  240. nfmt.LeadingZero=0;
  241. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep));
  242. nfmt.Grouping = StrToInt(szSep);
  243. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep));
  244. nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
  245. nfmt.NegativeOrder= 0;
  246. Int64ToStr(n, szTemp);
  247. // Should have passed in size
  248. if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, MAX_COMMA_NUMBER_SIZE) == 0)
  249. lstrcpy(pszResult, szTemp);
  250. return pszResult;
  251. }
  252. //
  253. // Add Peta 10^15 and Exa 10^18 to support 64-bit integers.
  254. //
  255. const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB,
  256. IDS_ORDERGB, IDS_ORDERTB, IDS_ORDERPB, IDS_ORDEREB};
  257. /* converts numbers into sort formats
  258. * 532 -> 523 bytes
  259. * 1340 -> 1.3KB
  260. * 23506 -> 23.5KB
  261. * -> 2.4MB
  262. * -> 5.2GB
  263. */
  264. LPTSTR WINAPI ShortSizeFormat64(__int64 dw64, LPTSTR szBuf)
  265. {
  266. int i;
  267. _int64 wInt;
  268. UINT wLen, wDec;
  269. TCHAR szTemp[MAX_COMMA_NUMBER_SIZE], szOrder[20], szFormat[5];
  270. if (dw64 < 1000) {
  271. wsprintf(szTemp, TEXT("%d"), LODWORD(dw64));
  272. i = 0;
  273. goto AddOrder;
  274. }
  275. for (i = 1; i<ARRAYSIZE(pwOrders)-1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++);
  276. /* do nothing */
  277. wInt = dw64 >> 10;
  278. AddCommas64(wInt, szTemp);
  279. wLen = lstrlen(szTemp);
  280. if (wLen < 3)
  281. {
  282. wDec = LODWORD(dw64 - wInt * 1024L) * 1000 / 1024;
  283. // At this point, wDec should be between 0 and 1000
  284. // we want get the top one (or two) digits.
  285. wDec /= 10;
  286. if (wLen == 2)
  287. wDec /= 10;
  288. // Note that we need to set the format before getting the
  289. // intl char.
  290. lstrcpy(szFormat, TEXT("%02d"));
  291. szFormat[2] = TEXT('0') + 3 - wLen;
  292. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
  293. szTemp+wLen, ARRAYSIZE(szTemp)-wLen);
  294. wLen = lstrlen(szTemp);
  295. wLen += wsprintf(szTemp+wLen, szFormat, wDec);
  296. }
  297. AddOrder:
  298. LoadString(HINST_THISDLL, pwOrders[i], szOrder, ARRAYSIZE(szOrder));
  299. wsprintf(szBuf, szOrder, (LPTSTR)szTemp);
  300. return szBuf;
  301. }
  302. #define c_szUninstallPolicy L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Uninstall"
  303. /*-------------------------------------------------------------------------
  304. Purpose: Helper function for ARP's policy check
  305. */
  306. DWORD ARPGetRestricted(LPCWSTR pszPolicy)
  307. {
  308. return SHGetRestriction(NULL, TEXT("Uninstall"), pszPolicy);
  309. }
  310. /*-------------------------------------------------------------------------
  311. Purpose: Return a policy string value
  312. */
  313. void ARPGetPolicyString(LPCWSTR pszPolicy, LPWSTR pszBuf, int cch)
  314. {
  315. DWORD dwSize, dwType;
  316. *pszBuf = 0;
  317. // Check local machine first and let it override what the
  318. // HKCU policy has done.
  319. dwSize = cch * sizeof(WCHAR);
  320. if (ERROR_SUCCESS != SHGetValueW(HKEY_LOCAL_MACHINE,
  321. c_szUninstallPolicy, pszPolicy,
  322. &dwType, pszBuf, &dwSize))
  323. {
  324. // Check current user if we didn't find anything for the local machine.
  325. dwSize = cch * sizeof(WCHAR);
  326. SHGetValueW(HKEY_CURRENT_USER,
  327. c_szUninstallPolicy, pszPolicy,
  328. &dwType, pszBuf, &dwSize);
  329. }
  330. }
  331. /*-------------------------------------------------------------------------
  332. Purpose: Returns TRUE if it's okay to start ARP.
  333. */
  334. BOOL _IsARPAllowed(void)
  335. {
  336. // ARP is forbidden if the entire CPL is disabled
  337. if (ARPGetRestricted(L"NoAddRemovePrograms"))
  338. {
  339. return FALSE;
  340. }
  341. // ARP is permitted if there exists a non-restricted page.
  342. BOOL fAnyPages = !ARPGetRestricted(L"NoRemovePage") ||
  343. !ARPGetRestricted(L"NoAddPage") ||
  344. !ARPGetRestricted(L"NoWindowsSetupPage");
  345. // If we are not a server SKU, then also check the new page.
  346. if (!fAnyPages && !IsOS(OS_ANYSERVER))
  347. {
  348. fAnyPages = !ARPGetRestricted(L"NoChooseProgramsPage");
  349. }
  350. return fAnyPages;
  351. }
  352. #ifndef DOWNLEVEL_PLATFORM
  353. /*-------------------------------------------------------------------------
  354. Purpose: Take the error message and give user feedback through messagebox
  355. */
  356. void _ARPErrorMessageBox(DWORD dwError)
  357. {
  358. TCHAR szErrorMsg[MAX_PATH];
  359. szErrorMsg[0] = 0;
  360. LPTSTR pszMsg = NULL;
  361. switch (dwError) {
  362. // The following error code cases are ignored.
  363. case ERROR_INSTALL_USEREXIT:
  364. case ERROR_SUCCESS_REBOOT_REQUIRED:
  365. case ERROR_SUCCESS_REBOOT_INITIATED:
  366. ASSERT(pszMsg == NULL);
  367. break;
  368. default:
  369. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0L, szErrorMsg,
  370. ARRAYSIZE(szErrorMsg), NULL);
  371. pszMsg = szErrorMsg;
  372. break;
  373. }
  374. if (pszMsg)
  375. {
  376. ShellMessageBox( g_hinst, NULL, pszMsg,
  377. MAKEINTRESOURCE( IDS_NAME ),
  378. MB_OK | MB_ICONEXCLAMATION);
  379. }
  380. }
  381. /*-------------------------------------------------------------------------
  382. Purpose: Format the SYSTEMTIME into the following format: "mm/dd/yy h:mm"
  383. */
  384. BOOL FormatSystemTimeString(LPSYSTEMTIME pst, LPTSTR pszStr, UINT cchStr)
  385. {
  386. BOOL bRet = FALSE;
  387. FILETIME ft = {0};
  388. if (SystemTimeToFileTime(pst, &ft))
  389. {
  390. DWORD dwFlags = FDTF_SHORTTIME | FDTF_SHORTDATE;
  391. bRet = SHFormatDateTime(&ft, &dwFlags, pszStr, cchStr);
  392. }
  393. return bRet;
  394. }
  395. #endif //DOWNLEVEL_PLATFORM
  396. /*-------------------------------------------------------------------------
  397. Purpose: Get the correct Date time format for specific locale
  398. */
  399. BOOL _GetLocaleDateTimeFormat(LPTSTR pszFormat, UINT cchFormat)
  400. {
  401. TCHAR szTime[DATEFORMAT_MAX];
  402. TCHAR szDate[DATEFORMAT_MAX];
  403. if (cchFormat >= (ARRAYSIZE(szTime) + ARRAYSIZE(szDate) + 2))
  404. {
  405. LCID lcid = LOCALE_USER_DEFAULT;
  406. if (GetLocaleInfo(lcid, LOCALE_STIMEFORMAT, szTime, ARRAYSIZE(szTime)) &&
  407. GetLocaleInfo(lcid, LOCALE_SSHORTDATE, szDate, ARRAYSIZE(szDate)))
  408. {
  409. wsprintf(pszFormat, TEXT("%s %s"), szDate, szTime);
  410. return TRUE;
  411. }
  412. }
  413. return FALSE;
  414. }
  415. /*-------------------------------------------------------------------------
  416. Purpose: Compare two SYSTEMTIME data
  417. Returnes : 1 : st1 > st2
  418. 0 : st1 == st2
  419. -1: st1 < st2
  420. NOTE: We do not compare seconds since ARP does not need that much precision.
  421. */
  422. int CompareSystemTime(SYSTEMTIME *pst1, SYSTEMTIME *pst2)
  423. {
  424. int iRet;
  425. if (pst1->wYear < pst2->wYear)
  426. iRet = -1;
  427. else if (pst1->wYear > pst2->wYear)
  428. iRet = 1;
  429. else if (pst1->wMonth < pst2->wMonth)
  430. iRet = -1;
  431. else if (pst1->wMonth > pst2->wMonth)
  432. iRet = 1;
  433. else if (pst1->wDay < pst2->wDay)
  434. iRet = -1;
  435. else if (pst1->wDay > pst2->wDay)
  436. iRet = 1;
  437. else if (pst1->wHour < pst2->wHour)
  438. iRet = -1;
  439. else if (pst1->wHour > pst2->wHour)
  440. iRet = 1;
  441. else if (pst1->wMinute < pst2->wMinute)
  442. iRet = -1;
  443. else if (pst1->wMinute > pst2->wMinute)
  444. iRet = 1;
  445. // else if (pst1->wSecond < pst2->wSecond)
  446. // iRet = -1;
  447. // else if (pst1->wSecond > pst2->wSecond)
  448. // iRet = 1;
  449. else
  450. iRet = 0;
  451. return(iRet);
  452. }
  453. #ifndef DOWNLEVEL_PLATFORM
  454. /*--------------------------------------------------------------------------
  455. Purpose: Window proc for the add later dialog box
  456. */
  457. BOOL_PTR CALLBACK AddLaterDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
  458. {
  459. switch (msg)
  460. {
  461. case WM_INITDIALOG:
  462. {
  463. PADDLATERDATA pald = (PADDLATERDATA)lp;
  464. // We should definitely have this (dli)
  465. ASSERT(pald);
  466. SYSTEMTIME stInit = {0};
  467. // Get the current local time
  468. GetLocalTime(&stInit);
  469. // Has this app already expired?
  470. if ((pald->dwMasks & ALD_EXPIRE) &&
  471. (CompareSystemTime(&pald->stExpire, &stInit) > 0))
  472. {
  473. // NO,
  474. // Assigned time does not make sense if the assigned time has already
  475. // passed
  476. if ((pald->dwMasks & ALD_ASSIGNED) &&
  477. (CompareSystemTime(&pald->stAssigned, &stInit) <= 0))
  478. pald->dwMasks &= ~ALD_ASSIGNED;
  479. // find the date/time picker window
  480. HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER);
  481. // always check "add later" radio button initially
  482. CheckDlgButton(hDlg, IDC_ADDLATER, BST_CHECKED);
  483. TCHAR szFormat[MAX_PATH];
  484. if (_GetLocaleDateTimeFormat(szFormat, ARRAYSIZE(szFormat)))
  485. {
  486. // set the locale date time format
  487. DateTime_SetFormat(hwndPicker, szFormat);
  488. // The new time can only be in the future, so set the current time
  489. // as the lower limit
  490. DateTime_SetRange(hwndPicker, GDTR_MIN, &stInit);
  491. // Do we have a schedule (in the future) already?
  492. // Schedule in the past means nothing
  493. if ((pald->dwMasks & ALD_SCHEDULE) &&
  494. (CompareSystemTime(&pald->stSchedule, &stInit) >= 0))
  495. {
  496. // Set our initial value to this schedule
  497. stInit = pald->stSchedule;
  498. }
  499. // Set the initial value in date/time picker
  500. DateTime_SetSystemtime(hwndPicker, GDT_VALID, &stInit);
  501. // Uncheck the SCHEDULE flag so that we know we don't have a new
  502. // schedule, yet
  503. pald->dwMasks &= ~ALD_SCHEDULE;
  504. SetWindowLongPtr(hDlg, DWLP_USER, lp);
  505. return TRUE;
  506. }
  507. }
  508. else
  509. {
  510. // Yes, it's expired, warn the user
  511. ShellMessageBox(g_hinst, hDlg, MAKEINTRESOURCE(IDS_EXPIRED),
  512. MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
  513. // Then end the dialog.
  514. EndDialog(hDlg, 0);
  515. }
  516. return FALSE;
  517. }
  518. break;
  519. case WM_COMMAND:
  520. switch (GET_WM_COMMAND_ID(wp, lp))
  521. {
  522. case IDC_ADDLATER:
  523. case IDC_UNSCHEDULE:
  524. {
  525. HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER);
  526. EnableWindow(hwndPicker, IsDlgButtonChecked(hDlg, IDC_ADDLATER));
  527. }
  528. break;
  529. case IDOK:
  530. {
  531. PADDLATERDATA pald = (PADDLATERDATA)GetWindowLongPtr(hDlg, DWLP_USER);
  532. // we did set window long ptr this should be there.
  533. ASSERT(pald);
  534. // did the user choose to add later?
  535. if (IsDlgButtonChecked(hDlg, IDC_ADDLATER))
  536. {
  537. // Yes
  538. // Let's find out if the time user has chosen is valid
  539. #define LATER_THAN_ASSIGNED_TIME 1
  540. #define LATER_THAN_EXPIRED_TIME 2
  541. int iStatus = 0;
  542. HWND hwndPicker = GetDlgItem(hDlg, IDC_PICKER);
  543. DateTime_GetSystemtime(hwndPicker, &pald->stSchedule);
  544. // Is this time later than the assigned time?
  545. if ((pald->dwMasks & ALD_ASSIGNED) &&
  546. (CompareSystemTime(&pald->stSchedule, &pald->stAssigned) > 0))
  547. iStatus = LATER_THAN_ASSIGNED_TIME;
  548. // Is this time later than the expired time?
  549. if ((pald->dwMasks & ALD_EXPIRE) &&
  550. (CompareSystemTime(&pald->stSchedule, &pald->stExpire) >= 0))
  551. iStatus = LATER_THAN_EXPIRED_TIME;
  552. // Is either of the above two cases TRUE?
  553. if (iStatus > 0)
  554. {
  555. TCHAR szDateTime[MAX_PATH];
  556. // Is the time user chose passed expired time or assigned?
  557. BOOL bExpired = (iStatus == LATER_THAN_EXPIRED_TIME);
  558. // Get the time string
  559. if (FormatSystemTimeString(bExpired ? &pald->stExpire : &pald->stAssigned,
  560. szDateTime, ARRAYSIZE(szDateTime)))
  561. {
  562. TCHAR szFinal[MAX_PATH * 2];
  563. TCHAR szWarn[MAX_PATH];
  564. LoadString(g_hinst, bExpired ? IDS_PASSEXPIRED : IDS_PASSASSIGNED,
  565. szWarn, ARRAYSIZE(szWarn));
  566. wsprintf(szFinal, szWarn, szDateTime, szDateTime);
  567. ShellMessageBox(g_hinst, hDlg, szFinal,
  568. MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
  569. }
  570. }
  571. else
  572. // No, we are okay to go
  573. pald->dwMasks |= ALD_SCHEDULE;
  574. }
  575. }
  576. //
  577. // fall through
  578. //
  579. case IDCANCEL:
  580. EndDialog(hDlg, (GET_WM_COMMAND_ID(wp, lp) == IDOK));
  581. break;
  582. default:
  583. return FALSE;
  584. }
  585. break;
  586. default:
  587. return FALSE;
  588. }
  589. return TRUE;
  590. }
  591. /*-------------------------------------------------------------------------
  592. Purpose: GetNewInstallTime
  593. Start up the Add Later dialog box to get the new install schedule
  594. (represented by a SYSTEMTIME data struct)
  595. */
  596. BOOL GetNewInstallTime(HWND hwndParent, PADDLATERDATA pal)
  597. {
  598. return (DialogBoxParam(g_hinst, MAKEINTRESOURCE(DLG_ADDLATER),
  599. hwndParent, AddLaterDlgProc, (LPARAM)pal) == IDOK);
  600. }
  601. #endif //DOWNLEVEL_PLATFORM
  602. // Take the name of the potential app folder and see if it ends with numbers or dots
  603. // if it does, let's separate the numbers and see if there is a match.
  604. // It's inspired by cases like Office8.0 or MSVC50 or Bookshelf98
  605. // NOTE: we can't use the key words without the numbers, it might lead to mistake
  606. // in case the user has two versions of the same software on one machine. (there might
  607. // be something we can do though, I am too tired to think about this now)
  608. void InsertSpaceBeforeVersion(LPCTSTR pszIn, LPTSTR pszOut)
  609. {
  610. ASSERT(IS_VALID_STRING_PTR(pszIn, -1));
  611. ASSERT(IS_VALID_STRING_PTR(pszOut, -1));
  612. // Copy the old string into the buffer
  613. lstrcpy(pszOut, pszIn);
  614. // Find the end of the string
  615. LPTSTR pszEnd = pszOut + lstrlen(pszOut);
  616. ASSERT(pszEnd > pszOut);
  617. // Go back until we can't see numbers or '.'
  618. LPTSTR pszLastChar = CharPrev(pszOut, pszEnd);
  619. LPTSTR pszPrev = pszLastChar;
  620. while ((pszPrev > pszOut) && (((*pszPrev <= TEXT('9')) && (*pszPrev >= TEXT('0'))) || (*pszPrev == TEXT('.'))))
  621. pszPrev = CharPrev(pszOut, pszPrev);
  622. // Did we find any numbers at the end?
  623. if ((pszPrev < pszLastChar) && IsCharAlphaNumeric(*pszPrev))
  624. {
  625. // Yes, let's stick a ' ' in between
  626. TCHAR szNumbers[MAX_PATH];
  627. lstrcpy(szNumbers, ++pszPrev);
  628. *(pszPrev++) = TEXT(' ');
  629. lstrcpy(pszPrev, szNumbers);
  630. }
  631. }
  632. #ifndef DOWNLEVEL_PLATFORM
  633. //
  634. // Basic sanity check on whether the app folder location is valid.
  635. // Return Value:
  636. // TRUE does not mean it is valid.
  637. // FALSE means it definitely is not valid.
  638. //
  639. BOOL IsValidAppFolderLocation(LPCTSTR pszFolder)
  640. {
  641. ASSERT(IS_VALID_STRING_PTR(pszFolder, -1));
  642. BOOL bRet = FALSE;
  643. if (!PathIsRoot(pszFolder) && PathFileExists(pszFolder) && PathIsDirectory(pszFolder))
  644. {
  645. TCHAR szPath[MAX_PATH];
  646. if (lstrcpy(szPath, pszFolder) && PathStripToRoot(szPath))
  647. bRet = (GetDriveType(szPath) == DRIVE_FIXED);
  648. }
  649. return bRet;
  650. }
  651. #ifdef WINNT
  652. EXTERN_C BOOL IsTerminalServicesRunning(void)
  653. {
  654. static int s_fIsTerminalServer = -1;
  655. if (s_fIsTerminalServer == -1)
  656. {
  657. BOOL TSAppServer;
  658. BOOL TSRemoteAdmin;
  659. OSVERSIONINFOEX osVersionInfo;
  660. DWORDLONG dwlConditionMask = 0;
  661. ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  662. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  663. osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL;
  664. VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
  665. TSAppServer = (int)VerifyVersionInfo(&osVersionInfo, VER_SUITENAME, dwlConditionMask);
  666. ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  667. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  668. osVersionInfo.wSuiteMask = VER_SUITE_SINGLEUSERTS;
  669. VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
  670. TSRemoteAdmin = (int)VerifyVersionInfo(&osVersionInfo, VER_SUITENAME, dwlConditionMask);
  671. if ( !TSRemoteAdmin & TSAppServer )
  672. {
  673. s_fIsTerminalServer = TRUE;
  674. }
  675. else
  676. {
  677. // do not treat tsremoteadmin as TS machine from the application compatability point of view.
  678. s_fIsTerminalServer = FALSE;
  679. }
  680. }
  681. return s_fIsTerminalServer ? TRUE : FALSE;
  682. }
  683. #endif //WINNT
  684. #endif //DOWNLEVEL_PLATFORM
  685. // returns TRUE if pszFile is a local file and on a fixed drive
  686. BOOL PathIsLocalAndFixed(LPCTSTR pszFile)
  687. {
  688. if (!pszFile || !pszFile[0])
  689. return FALSE;
  690. if (PathIsUNC(pszFile))
  691. return FALSE;
  692. TCHAR szDrive[MAX_PATH];
  693. lstrcpy(szDrive, pszFile);
  694. if (PathStripToRoot(szDrive) && GetDriveType(szDrive) != DRIVE_FIXED)
  695. return FALSE;
  696. return TRUE;
  697. }
  698. // This function will duplicate an APPCATEGORYINFOLIST and allocate the new copy
  699. // using COM memory allocation functions
  700. STDAPI _DuplicateCategoryList(APPCATEGORYINFOLIST * pacl, APPCATEGORYINFOLIST * paclNew)
  701. {
  702. HRESULT hres = E_FAIL;
  703. ASSERT(pacl && paclNew);
  704. ZeroMemory(paclNew, SIZEOF(APPCATEGORYINFOLIST));
  705. if (pacl && (pacl->cCategory > 0) && pacl->pCategoryInfo)
  706. {
  707. DWORD dwDesiredSize = pacl->cCategory * SIZEOF(APPCATEGORYINFO);
  708. APPCATEGORYINFO * paci = pacl->pCategoryInfo;
  709. paclNew->pCategoryInfo = (APPCATEGORYINFO *)SHAlloc(dwDesiredSize);
  710. if (paclNew->pCategoryInfo)
  711. {
  712. UINT iCategory = 0;
  713. paclNew->cCategory = 0;
  714. APPCATEGORYINFO * paciNew = paclNew->pCategoryInfo;
  715. while (paci && (iCategory < pacl->cCategory))
  716. {
  717. if (paci->pszDescription)
  718. {
  719. hmemcpy(paciNew, paci, SIZEOF(APPCATEGORYINFO));
  720. if (FAILED(SHStrDup(paci->pszDescription, &(paciNew->pszDescription))))
  721. {
  722. // We may be out of memory, stop here.
  723. ZeroMemory(paciNew, SIZEOF(APPCATEGORYINFO));
  724. break;
  725. }
  726. paciNew++;
  727. paclNew->cCategory++;
  728. }
  729. iCategory++;
  730. paci++;
  731. }
  732. hres = S_OK;
  733. }
  734. else
  735. hres = E_OUTOFMEMORY;
  736. }
  737. return hres;
  738. }
  739. STDAPI _DestroyCategoryList(APPCATEGORYINFOLIST * pacl)
  740. {
  741. if (pacl && pacl->pCategoryInfo)
  742. {
  743. UINT iCategory = 0;
  744. APPCATEGORYINFO * paci = pacl->pCategoryInfo;
  745. while (paci && (iCategory < pacl->cCategory))
  746. {
  747. if (paci->pszDescription)
  748. {
  749. SHFree(paci->pszDescription);
  750. }
  751. iCategory++;
  752. paci++;
  753. }
  754. SHFree(pacl->pCategoryInfo);
  755. }
  756. return S_OK;
  757. }