Leaked source code of windows server 2003
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.

1629 lines
45 KiB

  1. /*
  2. * Copyright (c) 2001 Microsoft Corporation
  3. *
  4. * Module Name:
  5. *
  6. * POP3oc.cpp
  7. *
  8. * Abstract:
  9. *
  10. * This file handles all messages passed by the OC Manager
  11. *
  12. * Author:
  13. *
  14. * Paolo Raden (paolora) Nov-20-2001
  15. *
  16. * Environment:
  17. *
  18. * User Mode
  19. */
  20. #define _POP3OC_CPP_
  21. #include <windows.h>
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include <tchar.h>
  25. #include <shlobj.h>
  26. #include <objbase.h>
  27. #include <shlwapi.h>
  28. #include <lm.h>
  29. #include <objidl.h>
  30. #include <psapi.h>
  31. #include "pop3oc.h"
  32. #include "ServiceUtil.h"
  33. #include "Pop3RegKeysUtil.h"
  34. #include <isexchng.h>
  35. #include <p3admin.h>
  36. #include <Pop3Server.h>
  37. #define _ASSERT(x) {}
  38. #include <ServUtil.h>
  39. #include <smtpinet.h>
  40. #pragma hdrstop
  41. // also referred to in pop3oc.h // forward reference
  42. DWORD OnPreinitialize();
  43. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc);
  44. DWORD OnSetLanguage();
  45. DWORD_PTR OnQueryImage();
  46. DWORD OnSetupRequestPages(UINT type, PVOID srp);
  47. DWORD OnQuerySelStateChange(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state, UINT flags);
  48. DWORD OnCalcDiskSpace(LPCTSTR ComponentId, LPCTSTR SubcomponentId, DWORD addComponent, HDSKSPC dspace);
  49. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue);
  50. DWORD OnNotificationFromQueue();
  51. DWORD OnQueryStepCount();
  52. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  53. DWORD OnCleanup();
  54. DWORD OnQueryState(LPCTSTR ComponentId, LPCTSTR SubcomponentId, UINT state);
  55. DWORD OnNeedMedia();
  56. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId);
  57. DWORD OnQuerySkipPage();
  58. DWORD OnWizardCreated();
  59. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per);
  60. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId);
  61. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId);
  62. VOID RemoveComponent(LPCTSTR ComponentId);
  63. BOOL StateInfo(PPER_COMPONENT_DATA cd, LPCTSTR SubcomponentId, BOOL *state);
  64. DWORD RegisterServers(HINF hinf, LPCTSTR component, DWORD state);
  65. DWORD EnumSections(HINF hinf, const TCHAR *component, const TCHAR *key, DWORD index, INFCONTEXT *pic, TCHAR *name);
  66. DWORD RegisterServices(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  67. DWORD CleanupNetShares(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  68. DWORD RunExternalProgram(PPER_COMPONENT_DATA cd, LPCTSTR component, DWORD state);
  69. HRESULT CreateLink( const TCHAR *sourcePath, const TCHAR *linkPath, const TCHAR *args, const TCHAR *sDesc );
  70. // POP 3 custom
  71. DWORD KillPop3Snapins();
  72. // for registering dlls
  73. typedef HRESULT (__stdcall *pfn)(void);
  74. #define KEYWORD_REGSVR TEXT("RegSvr")
  75. #define KEYWORD_UNREGSVR TEXT("UnregSvr")
  76. #define KEYWORD_UNINSTALL TEXT("Uninstall")
  77. #define KEYWORD_SOURCEPATH TEXT("SourcePath")
  78. #define KEYWORD_DELSHARE TEXT("DelShare")
  79. #define KEYWORD_ADDSERVICE TEXT("AddService")
  80. #define KEYWORD_DELSERVICE TEXT("DelService")
  81. #define KEYWORD_SHARENAME TEXT("Share")
  82. #define KEYWORD_RUN TEXT("Run")
  83. #define KEYVAL_SYSTEMSRC TEXT("SystemSrc")
  84. #define KEYWORD_COMMANDLINE TEXT("CommandLine")
  85. #define KEYWORD_TICKCOUNT TEXT("TickCount")
  86. // Services keywords/options
  87. #define KEYWORD_SERVICENAME TEXT("ServiceName")
  88. #define KEYWORD_DISPLAYNAME TEXT("DisplayName")
  89. #define KEYWORD_SERVICETYPE TEXT("ServiceType")
  90. #define KEYWORD_STARTTYPE TEXT("StartType")
  91. #define KEYWORD_ERRORCONTROL TEXT("ErrorControl")
  92. #define KEYWORD_IMAGEPATH TEXT("BinaryPathName")
  93. #define KEYWORD_LOADORDER TEXT("LoadOrderGroup")
  94. #define KEYWORD_DEPENDENCIES TEXT("Dependencies")
  95. #define KEYWORD_STARTNAME TEXT("ServiceStartName")
  96. #define KEYWORD_PASSWORD TEXT("Password")
  97. #define KEYVAL_ON TEXT("on")
  98. #define KEYVAL_OFF TEXT("off")
  99. #define KEYVAL_DEFAULT TEXT("default")
  100. const char gszRegisterSvrRoutine[] = "DllRegisterServer";
  101. const char gszUnregisterSvrRoutine[] = "DllUnregisterServer";
  102. BOOL g_fRebootNeed = FALSE;
  103. BOOL g_fExchange = FALSE;
  104. CServiceUtil *g_pServiceUtil = NULL;
  105. CServiceUtil *g_pServiceUtilWMI = NULL;
  106. CPop3RegKeysUtil *g_pPopRegKeys = NULL;
  107. PPER_COMPONENT_DATA _cd=NULL;
  108. /*
  109. * called by CRT when _DllMainCRTStartup is the DLL entry point
  110. */
  111. BOOL
  112. WINAPI
  113. DllMain(
  114. IN HINSTANCE hinstance,
  115. IN DWORD reason,
  116. IN LPVOID reserved
  117. )
  118. {
  119. BOOL b;
  120. UNREFERENCED_PARAMETER(reserved);
  121. b = true;
  122. switch(reason)
  123. {
  124. case DLL_PROCESS_ATTACH:
  125. ghinst = hinstance;
  126. loginit();
  127. // Fall through to process first thread
  128. case DLL_THREAD_ATTACH:
  129. b = true;
  130. break;
  131. case DLL_PROCESS_DETACH:
  132. break;
  133. case DLL_THREAD_DETACH:
  134. break;
  135. }
  136. return(b);
  137. }
  138. DWORD_PTR
  139. OcEntry(
  140. IN LPCTSTR ComponentId,
  141. IN LPCTSTR SubcomponentId,
  142. IN UINT Function,
  143. IN UINT Param1,
  144. IN OUT PVOID Param2
  145. )
  146. {
  147. DWORD_PTR rc;
  148. DebugTraceOCNotification(Function, ComponentId);
  149. logOCNotification(Function, ComponentId);
  150. switch(Function)
  151. {
  152. case OC_PREINITIALIZE:
  153. rc = OnPreinitialize();
  154. break;
  155. case OC_INIT_COMPONENT:
  156. rc = OnInitComponent(ComponentId, (PSETUP_INIT_COMPONENT)Param2);
  157. break;
  158. case OC_EXTRA_ROUTINES:
  159. rc = OnExtraRoutines(ComponentId, (PEXTRA_ROUTINES)Param2);
  160. break;
  161. case OC_SET_LANGUAGE:
  162. rc = OnSetLanguage();
  163. break;
  164. case OC_QUERY_IMAGE:
  165. rc = OnQueryImage();
  166. break;
  167. case OC_REQUEST_PAGES:
  168. rc = OnSetupRequestPages(Param1, Param2);
  169. break;
  170. case OC_QUERY_CHANGE_SEL_STATE:
  171. rc = OnQuerySelStateChange(ComponentId, SubcomponentId, Param1, (UINT)((UINT_PTR)Param2));
  172. break;
  173. case OC_CALC_DISK_SPACE:
  174. rc = OnCalcDiskSpace(ComponentId, SubcomponentId, Param1, Param2);
  175. break;
  176. case OC_QUEUE_FILE_OPS:
  177. rc = OnQueueFileOps(ComponentId, SubcomponentId, (HSPFILEQ)Param2);
  178. break;
  179. case OC_NOTIFICATION_FROM_QUEUE:
  180. rc = OnNotificationFromQueue();
  181. break;
  182. case OC_QUERY_STEP_COUNT:
  183. rc = OnQueryStepCount();
  184. break;
  185. case OC_COMPLETE_INSTALLATION:
  186. rc = OnCompleteInstallation(ComponentId, SubcomponentId);
  187. break;
  188. case OC_CLEANUP:
  189. rc = OnCleanup();
  190. break;
  191. case OC_QUERY_STATE:
  192. rc = OnQueryState(ComponentId, SubcomponentId, Param1);
  193. break;
  194. case OC_NEED_MEDIA:
  195. rc = OnNeedMedia();
  196. break;
  197. case OC_ABOUT_TO_COMMIT_QUEUE:
  198. rc = OnAboutToCommitQueue(ComponentId,SubcomponentId);
  199. break;
  200. case OC_QUERY_SKIP_PAGE:
  201. rc = OnQuerySkipPage();
  202. break;
  203. case OC_WIZARD_CREATED:
  204. rc = OnWizardCreated();
  205. break;
  206. default:
  207. rc = NO_ERROR;
  208. break;
  209. }
  210. DebugTrace(1, TEXT("processing completed"));
  211. logOCNotificationCompletion();
  212. return rc;
  213. }
  214. /*-------------------------------------------------------*/
  215. /*
  216. * OC Manager message handlers
  217. *
  218. *-------------------------------------------------------*/
  219. /* OnPreinitialize()
  220. *
  221. * handler for OC_PREINITIALIZE
  222. */
  223. DWORD
  224. OnPreinitialize(
  225. VOID
  226. )
  227. {
  228. #ifdef ANSI
  229. return OCFLAG_ANSI;
  230. #else
  231. return OCFLAG_UNICODE;
  232. #endif
  233. }
  234. /*
  235. * OnInitComponent()
  236. *
  237. * handler for OC_INIT_COMPONENT
  238. */
  239. DWORD OnInitComponent(LPCTSTR ComponentId, PSETUP_INIT_COMPONENT psc)
  240. {
  241. PPER_COMPONENT_DATA cd;
  242. INFCONTEXT context;
  243. TCHAR buf[256];
  244. HINF hinf;
  245. BOOL rc;
  246. // We should only uninstall if exchange is on the box
  247. g_fExchange = _IsExchangeInstalled();
  248. // add component to linked list
  249. if (!(cd = AddNewComponent(ComponentId)))
  250. return ERROR_NOT_ENOUGH_MEMORY;
  251. // store component inf handle
  252. cd->hinf = (psc->ComponentInfHandle == INVALID_HANDLE_VALUE)
  253. ? NULL
  254. : psc->ComponentInfHandle;
  255. // open the inf
  256. if (cd->hinf)
  257. SetupOpenAppendInfFile(NULL, cd->hinf,NULL);
  258. // copy helper routines and flags
  259. cd->HelperRoutines = psc->HelperRoutines;
  260. cd->Flags = psc->SetupData.OperationFlags;
  261. cd->SourcePath = NULL;
  262. // play
  263. srand(GetTickCount());
  264. return NO_ERROR;
  265. }
  266. /*
  267. * OnExtraRoutines()
  268. *
  269. * handler for OC_EXTRA_ROUTINES
  270. */
  271. DWORD OnExtraRoutines(LPCTSTR ComponentId, PEXTRA_ROUTINES per)
  272. {
  273. PPER_COMPONENT_DATA cd;
  274. if (!(cd = LocateComponent(ComponentId)))
  275. return NO_ERROR;
  276. memcpy(&cd->ExtraRoutines, per, per->size);
  277. return NO_ERROR;
  278. }
  279. /*
  280. * OnSetLanguage()
  281. *
  282. * handler for OC_SET_LANGUAGE
  283. */
  284. DWORD OnSetLanguage()
  285. {
  286. return false;
  287. }
  288. /*
  289. * OnSetLanguage()
  290. *
  291. * handler for OC_SET_LANGUAGE
  292. */
  293. DWORD_PTR OnQueryImage()
  294. {
  295. return (DWORD_PTR)LoadBitmap(NULL,MAKEINTRESOURCE(32754)); // OBM_CLOSE
  296. }
  297. /*
  298. * OnSetupRequestPages
  299. *
  300. * Prepares wizard pages and returns them to the OC Manager
  301. */
  302. DWORD OnSetupRequestPages(UINT type, PVOID srp)
  303. {
  304. return 0;
  305. }
  306. /*
  307. * OnWizardCreated()
  308. */
  309. DWORD OnWizardCreated()
  310. {
  311. return NO_ERROR;
  312. }
  313. /*
  314. * OnQuerySkipPage()
  315. *
  316. * don't let the user deselect the sam component
  317. */
  318. DWORD OnQuerySkipPage()
  319. {
  320. return false;
  321. }
  322. /*
  323. * OnQuerySelStateChange()
  324. *
  325. * don't let the user deselect the sam component
  326. */
  327. DWORD OnQuerySelStateChange(LPCTSTR ComponentId,
  328. LPCTSTR SubcomponentId,
  329. UINT state,
  330. UINT flags)
  331. {
  332. if (g_fExchange && (flags & OCQ_ACTUAL_SELECTION) && state)
  333. {
  334. log( TEXT("POP3OC: user tried to install %s while exchange is installed. Not supported."), SubcomponentId);
  335. MsgBox(NULL, IDS_ERR_EXCHANGE_INSTALLED, MB_OK);
  336. return FALSE;
  337. }
  338. return TRUE;
  339. }
  340. /*
  341. * OnCalcDiskSpace()
  342. *
  343. * handler for OC_ON_CALC_DISK_SPACE
  344. */
  345. DWORD OnCalcDiskSpace(LPCTSTR ComponentId,
  346. LPCTSTR SubcomponentId,
  347. DWORD addComponent,
  348. HDSKSPC dspace)
  349. {
  350. DWORD rc = NO_ERROR;
  351. TCHAR section[S_SIZE];
  352. PPER_COMPONENT_DATA cd;
  353. //
  354. // Param1 = 0 if for removing component or non-0 if for adding component
  355. // Param2 = HDSKSPC to operate on
  356. //
  357. // Return value is Win32 error code indicating outcome.
  358. //
  359. // In our case the private section for this component/subcomponent pair
  360. // is a simple standard inf install section, so we can use the high-level
  361. // disk space list api to do what we want.
  362. //
  363. if (!(cd = LocateComponent(ComponentId)))
  364. return NO_ERROR;
  365. _tcscpy(section, SubcomponentId);
  366. if (addComponent)
  367. {
  368. rc = SetupAddInstallSectionToDiskSpaceList(dspace,
  369. cd->hinf,
  370. NULL,
  371. section,
  372. 0,
  373. 0);
  374. }
  375. else
  376. {
  377. rc = SetupRemoveInstallSectionFromDiskSpaceList(dspace,
  378. cd->hinf,
  379. NULL,
  380. section,
  381. 0,
  382. 0);
  383. }
  384. if (!rc)
  385. rc = GetLastError();
  386. else
  387. rc = NO_ERROR;
  388. return rc;
  389. }
  390. /*
  391. * OnQueueFileOps()
  392. *
  393. * handler for OC_QUEUE_FILE_OPS
  394. */
  395. DWORD OnQueueFileOps(LPCTSTR ComponentId, LPCTSTR SubcomponentId, HSPFILEQ queue)
  396. {
  397. PPER_COMPONENT_DATA cd;
  398. BOOL state;
  399. BOOL rc;
  400. INFCONTEXT context;
  401. TCHAR section[256];
  402. TCHAR srcpathbuf[256];
  403. TCHAR *srcpath;
  404. if (!(cd = LocateComponent(ComponentId)))
  405. return NO_ERROR;
  406. if (!SubcomponentId || !*SubcomponentId)
  407. return NO_ERROR;
  408. cd->queue = queue;
  409. if (!StateInfo(cd, SubcomponentId, &state))
  410. return NO_ERROR;
  411. wsprintf(section, SubcomponentId);
  412. rc = TRUE;
  413. if (!state) {
  414. // being uninstalled. Fetch uninstall section name.
  415. rc = SetupFindFirstLine(cd->hinf,
  416. SubcomponentId,
  417. KEYWORD_UNINSTALL,
  418. &context);
  419. if (rc) {
  420. rc = SetupGetStringField(&context,
  421. 1,
  422. section,
  423. sizeof(section) / sizeof(TCHAR),
  424. NULL);
  425. }
  426. // POP3 Server Custom code goes here
  427. if (!_wcsicmp( SubcomponentId, L"Pop3Service"))
  428. {
  429. // Winpop Init 0
  430. TCHAR szSource[MAX_PATH+1];
  431. if (0 != GetSystemDirectory( szSource, MAX_PATH+1 ))
  432. {
  433. TCHAR szAppName[MAX_PATH+30];
  434. TCHAR szCommandLine[MAX_PATH+50];
  435. _tcscpy( szAppName, szSource );
  436. _tcscat( szAppName, _T("\\winpop.exe") );
  437. _tcscpy( szCommandLine, szAppName );
  438. _tcscat( szCommandLine, _T(" INIT 0") );
  439. STARTUPINFO si;
  440. PROCESS_INFORMATION pi;
  441. ZeroMemory( &si, sizeof(si) );
  442. ZeroMemory( &pi, sizeof(pi) );
  443. DWORD dwRet;
  444. if (CreateProcess( szAppName, szCommandLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
  445. do
  446. {
  447. dwRet = MsgWaitForMultipleObjects( 1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT );
  448. if( dwRet == WAIT_OBJECT_0 + 1 )
  449. {
  450. MSG msg;
  451. while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
  452. {
  453. TranslateMessage( &msg );
  454. DispatchMessage( &msg );
  455. }
  456. }
  457. }
  458. while( dwRet != WAIT_OBJECT_0 && dwRet != WAIT_FAILED );
  459. CloseHandle( pi.hProcess );
  460. CloseHandle( pi.hThread );
  461. }
  462. }
  463. // Kill all Pop3 snapins
  464. KillPop3Snapins();
  465. // also, unregister the dlls and kill services before deletion
  466. SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  467. SetupInstallFromInfSection(NULL,cd->hinf,section,SPINST_UNREGSVR,NULL,NULL,0,NULL,NULL,NULL,NULL);
  468. }
  469. if (rc) {
  470. // if uninstalling, don't use version checks
  471. rc = SetupInstallFilesFromInfSection(cd->hinf,
  472. NULL,
  473. queue,
  474. section,
  475. cd->SourcePath,
  476. state ? SP_COPY_NEWER : 0);
  477. }
  478. if (!rc)
  479. return GetLastError();
  480. return NO_ERROR;
  481. }
  482. /*
  483. * OnNotificationFromQueue()
  484. *
  485. * handler for OC_NOTIFICATION_FROM_QUEUE
  486. *
  487. * NOTE: although this notification is defined,
  488. * it is currently unimplemented in oc manager
  489. */
  490. DWORD OnNotificationFromQueue()
  491. {
  492. return NO_ERROR;
  493. }
  494. /*
  495. * OnQueryStepCount
  496. *
  497. * handler forOC_QUERY_STEP_COUNT
  498. */
  499. DWORD OnQueryStepCount()
  500. {
  501. return 2;
  502. }
  503. /*
  504. * OnCompleteInstallation
  505. *
  506. * handler for OC_COMPLETE_INSTALLATION
  507. */
  508. DWORD OnCompleteInstallation(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  509. {
  510. PPER_COMPONENT_DATA cd;
  511. INFCONTEXT context;
  512. TCHAR section[256];
  513. BOOL state;
  514. BOOL rc;
  515. DWORD Error = NO_ERROR;
  516. // Do post-installation processing in the cleanup section.
  517. // This way we know all compoents queued for installation
  518. // have beein installed before we do our stuff.
  519. if (!(cd = LocateComponent(ComponentId)))
  520. return NO_ERROR;
  521. if (!SubcomponentId || !*SubcomponentId)
  522. return NO_ERROR;
  523. if (!StateInfo(cd, SubcomponentId, &state))
  524. return NO_ERROR;
  525. wsprintf(section, SubcomponentId);
  526. rc = TRUE;
  527. if (!state) {
  528. // being uninstalled. Fetch uninstall section name.
  529. rc = SetupFindFirstLine(cd->hinf,
  530. SubcomponentId,
  531. KEYWORD_UNINSTALL,
  532. &context);
  533. if (rc) {
  534. rc = SetupGetStringField(&context,
  535. 1,
  536. section,
  537. sizeof(section) / sizeof(TCHAR),
  538. NULL);
  539. }
  540. }
  541. if (state) {
  542. //
  543. // installation
  544. //
  545. if (rc) {
  546. if ( NULL == g_pPopRegKeys )
  547. {
  548. g_pPopRegKeys = new CPop3RegKeysUtil();
  549. g_pPopRegKeys->Save();
  550. }
  551. // process the inf file
  552. rc = SetupInstallFromInfSection(NULL, // hwndOwner
  553. cd->hinf, // inf handle
  554. section, // name of component
  555. SPINST_ALL & ~SPINST_FILES,
  556. NULL, // relative key root
  557. NULL, // source root path
  558. 0, // copy flags
  559. NULL, // callback routine
  560. NULL, // callback routine context
  561. NULL, // device info set
  562. NULL); // device info struct
  563. if (rc) {
  564. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  565. Error = GetLastError();
  566. if (!rc && Error == ERROR_SECTION_NOT_FOUND) {
  567. rc = TRUE;
  568. Error = NO_ERROR;
  569. }
  570. if (rc) {
  571. if (Error == ERROR_SUCCESS_REBOOT_REQUIRED) {
  572. cd->HelperRoutines.SetReboot(cd->HelperRoutines.OcManagerContext,TRUE);
  573. }
  574. Error = NO_ERROR;
  575. rc = RunExternalProgram(cd, section, state);
  576. }
  577. }
  578. }
  579. } else {
  580. //
  581. // uninstallation
  582. //
  583. if (rc)
  584. {
  585. rc = RunExternalProgram(cd, section, state);
  586. }
  587. if (rc) {
  588. rc = CleanupNetShares(cd, section, state);
  589. }
  590. }
  591. HRESULT hr = CoInitialize( NULL );
  592. // POP3 Server Custom code goes here
  593. if (!_wcsicmp( SubcomponentId, L"Pop3Service"))
  594. {
  595. // installing
  596. TCHAR szSnapinName[64];
  597. int iLen=LoadString(ghinst, IDS_SNAPIN_NAME, szSnapinName, sizeof(szSnapinName)/sizeof(TCHAR));
  598. if(0==iLen)
  599. {
  600. _tcscpy(szSnapinName, _T("POP3 Service"));
  601. }
  602. if (state)
  603. {
  604. // Tooltip
  605. TCHAR szTooltip[INFOTIPSIZE];
  606. ZeroMemory( szTooltip, sizeof(szTooltip)/sizeof(TCHAR) );
  607. LoadString(ghinst, IDS_SHORTCUT_TOOLTIP, szTooltip, sizeof(szTooltip)/sizeof(TCHAR) );
  608. // Create the shortcut
  609. TCHAR szDest[MAX_PATH+70];
  610. if (TRUE == SHGetSpecialFolderPath( 0, szDest, CSIDL_COMMON_ADMINTOOLS, FALSE ))
  611. {
  612. TCHAR szSource[MAX_PATH+1];
  613. if (0 != GetSystemDirectory( szSource, MAX_PATH+1 ))
  614. {
  615. _tcscat( szSource, _T("\\p3server.msc") );
  616. _tcscat( szDest, _T("\\") );
  617. _tcscat( szDest, szSnapinName);
  618. _tcscat( szDest, _T(".lnk") );
  619. CreateLink( szSource, szDest, 0, szTooltip );
  620. }
  621. }
  622. // Winpop Init 1
  623. TCHAR szSource[MAX_PATH+1];
  624. if (0 != GetSystemDirectory( szSource, MAX_PATH+1 ))
  625. {
  626. TCHAR szAppName[MAX_PATH+30];
  627. TCHAR szCommandLine[MAX_PATH+50];
  628. _tcscpy( szAppName, szSource );
  629. _tcscat( szAppName, _T("\\winpop.exe") );
  630. _tcscpy( szCommandLine, szAppName );
  631. _tcscat( szCommandLine, _T(" INIT 1") );
  632. STARTUPINFO si;
  633. PROCESS_INFORMATION pi;
  634. ZeroMemory( &si, sizeof(si) );
  635. ZeroMemory( &pi, sizeof(pi) );
  636. DWORD dwRet;
  637. if (CreateProcess( szAppName, szCommandLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
  638. do
  639. {
  640. dwRet = MsgWaitForMultipleObjects( 1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT );
  641. if( dwRet == WAIT_OBJECT_0 + 1 )
  642. {
  643. MSG msg;
  644. while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
  645. {
  646. TranslateMessage( &msg );
  647. DispatchMessage( &msg );
  648. }
  649. }
  650. }
  651. while( dwRet != WAIT_OBJECT_0 && dwRet != WAIT_FAILED );
  652. CloseHandle( pi.hProcess );
  653. CloseHandle( pi.hThread );
  654. }
  655. // Add perf counters
  656. if (0 != GetSystemDirectory( szSource, MAX_PATH+1 ))
  657. {
  658. TCHAR szAppName[MAX_PATH+30];
  659. TCHAR szCommandLine[MAX_PATH*2+50];
  660. _tcscpy( szAppName, szSource );
  661. _tcscat( szAppName, _T("\\lodctr.exe") );
  662. _tcscpy( szCommandLine, szAppName );
  663. _tcscat( szCommandLine, _T(" ") );
  664. _tcscat( szCommandLine, szSource );
  665. _tcscat( szCommandLine, _T("\\POP3Server\\pop3perf.ini") );
  666. STARTUPINFO si;
  667. PROCESS_INFORMATION pi;
  668. ZeroMemory( &si, sizeof(si) );
  669. ZeroMemory( &pi, sizeof(pi) );
  670. DWORD dwRet;
  671. if (CreateProcess( szAppName, szCommandLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
  672. do
  673. {
  674. dwRet = MsgWaitForMultipleObjects( 1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT );
  675. if( dwRet == WAIT_OBJECT_0 + 1 )
  676. {
  677. MSG msg;
  678. while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
  679. {
  680. TranslateMessage( &msg );
  681. DispatchMessage( &msg );
  682. }
  683. }
  684. }
  685. while( dwRet != WAIT_OBJECT_0 && dwRet != WAIT_FAILED );
  686. CloseHandle( pi.hProcess );
  687. CloseHandle( pi.hThread );
  688. }
  689. // Restore the regkeys to their original state for uninstall
  690. if ( NULL != g_pPopRegKeys )
  691. {
  692. g_pPopRegKeys->Restore();
  693. g_pPopRegKeys = NULL;
  694. }
  695. }
  696. // removing
  697. else
  698. {
  699. // delete the shortcut
  700. TCHAR szPath[MAX_PATH+70];
  701. if (TRUE == SHGetSpecialFolderPath( 0, szPath, CSIDL_COMMON_ADMINTOOLS, FALSE ))
  702. {
  703. _tcscat( szPath, _T("\\") );
  704. _tcscat( szPath, szSnapinName);
  705. _tcscat( szPath, _T(".lnk") );
  706. DeleteFile( szPath );
  707. }
  708. TCHAR szSource[MAX_PATH+1];
  709. TCHAR szStoreDllName[MAX_PATH+30];
  710. // Remove perf counters
  711. if (0 != GetSystemDirectory( szSource, MAX_PATH+1 ))
  712. {
  713. TCHAR szAppName[MAX_PATH+30];
  714. TCHAR szCommandLine[MAX_PATH*2+50];
  715. _tcscpy( szAppName, szSource );
  716. _tcscat( szAppName, _T("\\unlodctr.exe") );
  717. _tcscpy( szCommandLine, szAppName );
  718. _tcscat( szCommandLine, _T(" pop3svc") );
  719. _tcscpy( szStoreDllName, szSource);
  720. _tcscat( szStoreDllName, _T("\\POP3Server\\P3Store.dll"));
  721. STARTUPINFO si;
  722. PROCESS_INFORMATION pi;
  723. ZeroMemory( &si, sizeof(si) );
  724. ZeroMemory( &pi, sizeof(pi) );
  725. DWORD dwRet;
  726. if (CreateProcess( szAppName, szCommandLine, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
  727. do
  728. {
  729. dwRet = MsgWaitForMultipleObjects( 1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT );
  730. if( dwRet == WAIT_OBJECT_0 + 1 )
  731. {
  732. MSG msg;
  733. while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
  734. {
  735. TranslateMessage( &msg );
  736. DispatchMessage( &msg );
  737. }
  738. }
  739. }
  740. while( dwRet != WAIT_OBJECT_0 && dwRet != WAIT_FAILED );
  741. CloseHandle( pi.hProcess );
  742. CloseHandle( pi.hThread );
  743. }
  744. //Before we restore the service, wait max of 30 seconds for p3store.dll to be deleted
  745. int iCountDown=15;
  746. while( ( INVALID_FILE_ATTRIBUTES != GetFileAttributes(szStoreDllName) ) &&
  747. ( iCountDown >0 ) )
  748. {
  749. Sleep(2000);
  750. iCountDown--;
  751. }
  752. if ( NULL != g_pServiceUtil )
  753. {
  754. g_pServiceUtil->RestoreServiceState( IISADMIN_SERVICE_NAME );
  755. delete g_pServiceUtil;
  756. g_pServiceUtil = NULL;
  757. }
  758. if ( NULL != g_pServiceUtilWMI )
  759. {
  760. g_pServiceUtilWMI->RestoreServiceState( WMI_SERVICE_NAME );
  761. delete g_pServiceUtilWMI;
  762. g_pServiceUtilWMI = NULL;
  763. }
  764. // Remove Dirs for files
  765. if (0 != GetSystemDirectory( szPath, MAX_PATH+1 ))
  766. {
  767. _tcscat( szPath, _T("\\POP3Server") );
  768. RemoveDirectory( szPath );
  769. }
  770. }
  771. }
  772. // POP3 Admin
  773. else if (!_wcsicmp( SubcomponentId, L"Pop3Admin" ))
  774. {
  775. // installing
  776. if (state)
  777. {
  778. }
  779. // removing
  780. else
  781. {
  782. TCHAR szPath[MAX_PATH+1];
  783. if (0 != GetSystemDirectory( szPath, MAX_PATH+1 ))
  784. {
  785. _tcscat( szPath, _T("\\ServerAppliance\\Web\\Mail") );
  786. RemoveDirectory( szPath );
  787. }
  788. }
  789. // stop the elementmgr service
  790. if ( _IsServiceRunning( _T("elementmgr")))
  791. {
  792. hr = _StopService( _T("elementmgr"), FALSE );
  793. if ( S_OK != hr )
  794. log( _T("POP3OC:OnCompleteInstallation: Unable to stop elementmgr.\r\n") );
  795. }
  796. }
  797. CoUninitialize();
  798. if (!rc && (Error == NO_ERROR) ) {
  799. Error = GetLastError( );
  800. }
  801. return Error;
  802. }
  803. /*
  804. * OnCleanup()
  805. *
  806. * handler for OC_CLEANUP
  807. */
  808. DWORD OnCleanup()
  809. {
  810. return NO_ERROR;
  811. }
  812. /*
  813. * OnQueryState()
  814. *
  815. * handler for OC_QUERY_STATE
  816. */
  817. DWORD OnQueryState(LPCTSTR ComponentId,
  818. LPCTSTR SubcomponentId,
  819. UINT state)
  820. {
  821. return SubcompUseOcManagerDefault;
  822. }
  823. /*
  824. * OnNeedMedia()
  825. *
  826. * handler for OC_NEED_MEDIA
  827. */
  828. DWORD OnNeedMedia()
  829. {
  830. return false;
  831. }
  832. /*
  833. * OnAboutToCommitQueue()
  834. *
  835. * handler for OC_ABOUT_TO_COMMIT_QUEUE
  836. */
  837. DWORD OnAboutToCommitQueue(LPCTSTR ComponentId, LPCTSTR SubcomponentId)
  838. {
  839. PPER_COMPONENT_DATA cd;
  840. BOOL state;
  841. BOOL rc;
  842. INFCONTEXT context;
  843. TCHAR section[256];
  844. TCHAR srcpathbuf[256];
  845. TCHAR *srcpath;
  846. if (!(cd = LocateComponent(ComponentId)))
  847. return NO_ERROR;
  848. if (!SubcomponentId || !*SubcomponentId)
  849. return NO_ERROR;
  850. if (!StateInfo(cd, SubcomponentId, &state))
  851. return NO_ERROR;
  852. //
  853. // only do stuff on uninstall
  854. //
  855. if (state) {
  856. return NO_ERROR;
  857. }
  858. // Fetch uninstall section name.
  859. rc = SetupFindFirstLine(
  860. cd->hinf,
  861. SubcomponentId,
  862. KEYWORD_UNINSTALL,
  863. &context);
  864. if (rc) {
  865. rc = SetupGetStringField(
  866. &context,
  867. 1,
  868. section,
  869. sizeof(section) / sizeof(TCHAR),
  870. NULL);
  871. }
  872. // POP3 Server Custom code goes here
  873. if (rc)
  874. {
  875. if (!_wcsicmp( SubcomponentId, L"Pop3Service"))
  876. { // Stop IISAdmin so that we can complete uninstall
  877. if ( NULL == g_pServiceUtil )
  878. {
  879. g_pServiceUtil = new CServiceUtil();
  880. if ( NULL != g_pServiceUtil )
  881. {
  882. g_pServiceUtil->StopService( IISADMIN_SERVICE_NAME );
  883. }
  884. }
  885. }
  886. // Stop WMI so that we can complete uninstall
  887. if ( NULL == g_pServiceUtilWMI )
  888. {
  889. g_pServiceUtilWMI = new CServiceUtil();
  890. if ( NULL != g_pServiceUtilWMI )
  891. {
  892. g_pServiceUtilWMI->StopService( WMI_SERVICE_NAME );
  893. }
  894. }
  895. }
  896. // Move Migration stuff to Mailroot
  897. // We will not fail uninstall if something fails in this section
  898. HKEY hKey;
  899. DWORD dwType = REG_SZ, dwSize;
  900. UINT uiRC;
  901. long lRC;
  902. TCHAR sCopyFrom[MAX_PATH+1], sCopyTo[MAX_PATH+1];
  903. // Get the mail root
  904. lRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, POP3SERVER_SOFTWARE_SUBKEY, 0, KEY_QUERY_VALUE, &hKey );
  905. if ( ERROR_SUCCESS == lRC )
  906. {
  907. dwSize = sizeof( sCopyTo )/sizeof(TCHAR);
  908. lRC = RegQueryValueEx( hKey, VALUENAME_MAILROOT, 0, &dwType, reinterpret_cast<LPBYTE>( sCopyTo ), &dwSize );
  909. RegCloseKey( hKey );
  910. }
  911. // Get the current location
  912. if ( ERROR_SUCCESS == lRC )
  913. {
  914. dwSize = sizeof( sCopyFrom )/sizeof(TCHAR);
  915. uiRC = GetSystemDirectory( sCopyFrom, dwSize );
  916. if ( 0 != uiRC && dwSize > uiRC )
  917. lRC = ERROR_SUCCESS;
  918. else
  919. lRC = GetLastError();
  920. }
  921. if (rc)
  922. rc = SetupInstallServicesFromInfSection(cd->hinf, section, 0);
  923. if (rc) {
  924. rc = SetupInstallFromInfSection(
  925. NULL,
  926. cd->hinf,
  927. section,
  928. SPINST_ALL & ~SPINST_FILES,
  929. NULL,
  930. NULL,
  931. 0,
  932. NULL,
  933. NULL,
  934. NULL,
  935. NULL);
  936. }
  937. if (rc) {
  938. SetLastError(NO_ERROR);
  939. }
  940. return GetLastError();
  941. }
  942. /*
  943. * AddNewComponent()
  944. *
  945. * add new compononent to the top of the component list
  946. */
  947. PPER_COMPONENT_DATA AddNewComponent(LPCTSTR ComponentId)
  948. {
  949. PPER_COMPONENT_DATA data;
  950. data = (PPER_COMPONENT_DATA)LocalAlloc(LPTR,sizeof(PER_COMPONENT_DATA));
  951. if (!data)
  952. return data;
  953. data->ComponentId = (TCHAR *)LocalAlloc(LMEM_FIXED,
  954. (_tcslen(ComponentId) + 1) * sizeof(TCHAR));
  955. if(data->ComponentId)
  956. {
  957. _tcscpy((TCHAR *)data->ComponentId, ComponentId);
  958. // Stick at head of list
  959. data->Next = gcd;
  960. gcd = data;
  961. }
  962. else
  963. {
  964. LocalFree((HLOCAL)data);
  965. data = NULL;
  966. }
  967. return(data);
  968. }
  969. /*
  970. * LocateComponent()
  971. *
  972. * returns a compoent struct that matches the
  973. * passed component id.
  974. */
  975. PPER_COMPONENT_DATA LocateComponent(LPCTSTR ComponentId)
  976. {
  977. PPER_COMPONENT_DATA p;
  978. for (p = gcd; p; p=p->Next)
  979. {
  980. if (!_tcsicmp(p->ComponentId, ComponentId))
  981. return p;
  982. }
  983. return NULL;
  984. }
  985. /*
  986. * RemoveComponent()
  987. *
  988. * yanks a component from our linked list of components
  989. */
  990. VOID RemoveComponent(LPCTSTR ComponentId)
  991. {
  992. PPER_COMPONENT_DATA p, prev;
  993. for (prev = NULL, p = gcd; p; prev = p, p = p->Next)
  994. {
  995. if (!_tcsicmp(p->ComponentId, ComponentId))
  996. {
  997. LocalFree((HLOCAL)p->ComponentId);
  998. if (p->SourcePath)
  999. LocalFree((HLOCAL)p->SourcePath);
  1000. if (prev)
  1001. prev->Next = p->Next;
  1002. else
  1003. gcd = p->Next;
  1004. LocalFree((HLOCAL)p);
  1005. return;
  1006. }
  1007. }
  1008. }
  1009. // loads current selection state info into "state" and
  1010. // returns whether the selection state was changed
  1011. BOOL
  1012. StateInfo(
  1013. PPER_COMPONENT_DATA cd,
  1014. LPCTSTR SubcomponentId,
  1015. BOOL *state
  1016. )
  1017. {
  1018. BOOL rc = TRUE;
  1019. assert(state);
  1020. // otherwise, check for a change in installation state
  1021. *state = cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  1022. SubcomponentId,
  1023. OCSELSTATETYPE_CURRENT);
  1024. if (*state == cd->HelperRoutines.QuerySelectionState(cd->HelperRoutines.OcManagerContext,
  1025. SubcomponentId,
  1026. OCSELSTATETYPE_ORIGINAL))
  1027. {
  1028. // no change
  1029. rc = FALSE;
  1030. }
  1031. // if this is gui mode setup, presume the state has changed to force
  1032. // an installation (or uninstallation)
  1033. if (!(cd->Flags & SETUPOP_STANDALONE) && *state)
  1034. rc = TRUE;
  1035. return rc;
  1036. }
  1037. /*
  1038. * EnumSections()
  1039. *
  1040. * finds the name of a section for a specified keyword
  1041. */
  1042. DWORD
  1043. EnumSections(
  1044. HINF hinf,
  1045. const TCHAR *component,
  1046. const TCHAR *key,
  1047. DWORD index,
  1048. INFCONTEXT *pic,
  1049. TCHAR *name
  1050. )
  1051. {
  1052. TCHAR section[S_SIZE];
  1053. if (!SetupFindFirstLine(hinf, component, NULL, pic))
  1054. return 0;
  1055. if (!SetupFindNextMatchLine(pic, key, pic))
  1056. return 0;
  1057. if (index > SetupGetFieldCount(pic))
  1058. return 0;
  1059. if (!SetupGetStringField(pic, index, section, sizeof(section)/sizeof(TCHAR), NULL))
  1060. return 0;
  1061. if (name)
  1062. _tcscpy(name, section);
  1063. return SetupFindFirstLine(hinf, section, NULL, pic);
  1064. }
  1065. DWORD
  1066. OcLog(
  1067. LPCTSTR ComponentId,
  1068. UINT level,
  1069. LPCTSTR sz
  1070. )
  1071. {
  1072. TCHAR fmt[5000];
  1073. PPER_COMPONENT_DATA cd;
  1074. if (!(cd = LocateComponent(ComponentId)))
  1075. return NO_ERROR;
  1076. assert(cd->ExtraRoutines.LogError);
  1077. assert(level);
  1078. assert(sz);
  1079. _tcscpy(fmt, TEXT("%s: %s"));
  1080. return cd->ExtraRoutines.LogError(cd->HelperRoutines.OcManagerContext,
  1081. level,
  1082. fmt,
  1083. ComponentId,
  1084. sz);
  1085. }
  1086. DWORD
  1087. CleanupNetShares(
  1088. PPER_COMPONENT_DATA cd,
  1089. LPCTSTR component,
  1090. DWORD state)
  1091. {
  1092. INFCONTEXT ic;
  1093. TCHAR sname[S_SIZE];
  1094. DWORD section;
  1095. TCHAR *keyword;
  1096. if (state) {
  1097. return NO_ERROR;
  1098. } else {
  1099. keyword = KEYWORD_DELSHARE;
  1100. }
  1101. for (section = 1;
  1102. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1103. section++)
  1104. {
  1105. INFCONTEXT sic;
  1106. NET_API_STATUS netStat;
  1107. CHAR Temp[SBUF_SIZE];
  1108. TCHAR ShareName[ SBUF_SIZE ];
  1109. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_SHARENAME, &sic))
  1110. {
  1111. log( TEXT("POP3OC: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_SHARENAME );
  1112. continue;
  1113. }
  1114. if (!SetupGetStringField(&sic, 1, ShareName, SBUF_SIZE, NULL))
  1115. {
  1116. log( TEXT("POP3OC: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_SHARENAME );
  1117. continue;
  1118. }
  1119. #ifdef UNICODE
  1120. netStat = NetShareDel( NULL, ShareName, 0 );
  1121. #else // UNICODE
  1122. WCHAR ShareNameW[ SBUF_SIZE ];
  1123. mbstowcs( ShareNameW, ShareName, lstrlen(ShareName));
  1124. netStat = NetShareDel( NULL, ShareNameW, 0 );
  1125. #endif // UNICODE
  1126. if ( netStat != NERR_Success )
  1127. {
  1128. log( TEXT("POP3OC: Failed to remove %s share. Error 0x%08x\r\n"), ShareName, netStat );
  1129. continue;
  1130. }
  1131. log( TEXT("POP3OC: %s share removed successfully.\r\n"), ShareName );
  1132. }
  1133. return TRUE;
  1134. }
  1135. DWORD
  1136. RunExternalProgram(
  1137. PPER_COMPONENT_DATA cd,
  1138. LPCTSTR component,
  1139. DWORD state)
  1140. {
  1141. INFCONTEXT ic;
  1142. TCHAR sname[S_SIZE];
  1143. DWORD section;
  1144. TCHAR *keyword;
  1145. keyword = KEYWORD_RUN;
  1146. for (section = 1;
  1147. EnumSections(cd->hinf, component, keyword, section, &ic, sname);
  1148. section++)
  1149. {
  1150. INFCONTEXT sic;
  1151. TCHAR CommandLine[ SBUF_SIZE ];
  1152. CHAR szTickCount[ SBUF_SIZE ];
  1153. ULONG TickCount;
  1154. BOOL b;
  1155. STARTUPINFO startupinfo;
  1156. PROCESS_INFORMATION process_information;
  1157. DWORD dwErr;
  1158. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_COMMANDLINE , &sic))
  1159. {
  1160. log( TEXT("POP3OC: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_COMMANDLINE );
  1161. continue;
  1162. }
  1163. if (!SetupGetStringField(&sic, 1, CommandLine, SBUF_SIZE, NULL))
  1164. {
  1165. log( TEXT("POP3OC: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_COMMANDLINE );
  1166. continue;
  1167. }
  1168. if (!SetupFindFirstLine(cd->hinf, sname, KEYWORD_TICKCOUNT, &sic))
  1169. {
  1170. log( TEXT("POP3OC: %s INF error - unable to find %s\r\n"), keyword, KEYWORD_TICKCOUNT );
  1171. continue;
  1172. }
  1173. if (!SetupGetStringFieldA(&sic, 1, szTickCount, SBUF_SIZE, NULL))
  1174. {
  1175. log( TEXT("POP3OC: %s INF error - incorrect %s line\r\n"), keyword, KEYWORD_TICKCOUNT );
  1176. continue;
  1177. }
  1178. TickCount = atoi( szTickCount );
  1179. ZeroMemory( &startupinfo, sizeof(startupinfo) );
  1180. startupinfo.cb = sizeof(startupinfo);
  1181. startupinfo.dwFlags = STARTF_USESHOWWINDOW;
  1182. startupinfo.wShowWindow = SW_HIDE | SW_SHOWMINNOACTIVE;
  1183. b = CreateProcess( NULL,
  1184. CommandLine,
  1185. NULL,
  1186. NULL,
  1187. FALSE,
  1188. CREATE_DEFAULT_ERROR_MODE,
  1189. NULL,
  1190. NULL,
  1191. &startupinfo,
  1192. &process_information );
  1193. if ( !b )
  1194. {
  1195. log( TEXT("POP3OC: failed to spawn %s process.\r\n"), CommandLine );
  1196. continue;
  1197. }
  1198. dwErr = WaitForSingleObject( process_information.hProcess, TickCount * 1000 );
  1199. if ( dwErr != NO_ERROR )
  1200. {
  1201. log( TEXT("POP3OC: WaitForSingleObject() failed. Error 0x%08x\r\n"), dwErr );
  1202. TerminateProcess( process_information.hProcess, -1 );
  1203. CloseHandle( process_information.hProcess );
  1204. CloseHandle( process_information.hThread );
  1205. continue;
  1206. }
  1207. CloseHandle( process_information.hProcess );
  1208. CloseHandle( process_information.hThread );
  1209. log( TEXT("POP3OC: %s successfully completed within %u seconds.\r\n"), CommandLine, TickCount );
  1210. }
  1211. return TRUE;
  1212. }
  1213. HRESULT CreateLink( const TCHAR *sourcePath, const TCHAR *linkPath, const TCHAR *args, const TCHAR *sDesc )
  1214. {
  1215. CoInitialize( NULL );
  1216. IShellLink* pShellLink = NULL;
  1217. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  1218. IID_IShellLink, reinterpret_cast<void**>(&pShellLink));
  1219. if (FAILED(hr))
  1220. return hr;
  1221. hr = pShellLink->SetPath(sourcePath);
  1222. if (FAILED(hr))
  1223. return hr;
  1224. hr = pShellLink->SetArguments(args);
  1225. if (FAILED(hr))
  1226. return hr;
  1227. hr = pShellLink->SetDescription(sDesc);
  1228. if (FAILED(hr))
  1229. return hr;
  1230. IPersistFile* pPersistFile = NULL;
  1231. hr = pShellLink->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&pPersistFile));
  1232. if (FAILED(hr))
  1233. return hr;
  1234. TCHAR* szTemp = new TCHAR[(sizeof(TCHAR) * _tcslen(linkPath)) + sizeof(TCHAR)];
  1235. if (!szTemp)
  1236. return E_OUTOFMEMORY;
  1237. _tcscpy( szTemp, linkPath );
  1238. hr = pPersistFile->Save(szTemp, TRUE);
  1239. if (FAILED(hr))
  1240. return hr;
  1241. pPersistFile->Release();
  1242. pShellLink->Release();
  1243. CoUninitialize();
  1244. delete [] szTemp;
  1245. return S_OK;
  1246. }
  1247. //Get a complete
  1248. int GetProcesses (DWORD ** lplp)
  1249. {
  1250. *lplp = NULL;
  1251. // according to docs (and other places), there's no scheme to tell,
  1252. // a priori, how many procs there are. So use loop below:
  1253. DWORD * lpids = NULL;
  1254. DWORD dwcb = sizeof(DWORD), dwcbNeeded;
  1255. do {
  1256. // alloc based on current dwcb.
  1257. lpids = (DWORD *)malloc (dwcb);
  1258. if (!lpids)
  1259. return 0;
  1260. dwcbNeeded = 0;
  1261. BOOL b = EnumProcesses (lpids, dwcb, &dwcbNeeded);
  1262. if ((b == FALSE) || (dwcbNeeded == 0)) {
  1263. // error!
  1264. free (lpids);
  1265. return 0;
  1266. }
  1267. if (dwcbNeeded == dwcb) {
  1268. free (lpids);
  1269. dwcb *= 2;
  1270. continue;
  1271. }
  1272. // if we got here, we have a complete list of procs
  1273. break;
  1274. } while (1);
  1275. *lplp = lpids;
  1276. return dwcbNeeded/sizeof(DWORD);
  1277. }
  1278. int GetModules (HANDLE hProcess, HMODULE ** lplp)
  1279. {
  1280. *lplp = NULL;
  1281. HMODULE * lpMods = NULL;
  1282. DWORD dwcb = sizeof(HMODULE), dwcbNeeded;
  1283. do {
  1284. // alloc based on current dwcb.
  1285. lpMods = (HMODULE *)malloc (dwcb);
  1286. if (!lpMods)
  1287. return 0;
  1288. dwcbNeeded = 0;
  1289. BOOL b = EnumProcessModules (hProcess, lpMods, dwcb, &dwcbNeeded);
  1290. if ((b == FALSE) || (dwcbNeeded == 0)) {
  1291. // error!
  1292. free (lpMods);
  1293. return 0;
  1294. }
  1295. // unlike calls to EnumProcesses, the last param of EnumProcessModules
  1296. // is actually useful: so, use it.
  1297. if (dwcbNeeded > dwcb) {
  1298. free (lpMods);
  1299. dwcb = dwcbNeeded;
  1300. continue;
  1301. }
  1302. // if we got here, we have a complete list of modules
  1303. break;
  1304. } while (1);
  1305. *lplp = lpMods;
  1306. return dwcbNeeded/sizeof(HMODULE);
  1307. }
  1308. DWORD KillPop3Snapins()
  1309. {
  1310. DWORD * lpProcs = NULL;
  1311. int iProcs = GetProcesses (&lpProcs);
  1312. if (!lpProcs)
  1313. return false;
  1314. bool b = false;
  1315. HANDLE hProcess;
  1316. HMODULE hModule;
  1317. DWORD cbReturned;
  1318. TCHAR szName[MAX_PATH];
  1319. HMODULE *lpMods;
  1320. int iMods;
  1321. // for each proc, get its name, and see if it's MMC
  1322. for (int i=0; i<iProcs; i++)
  1323. {
  1324. hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, lpProcs[i]);
  1325. if (hProcess != NULL)
  1326. { // first module is the .exe....
  1327. hModule = NULL;
  1328. cbReturned = 0;
  1329. if ( EnumProcessModules (hProcess, &hModule, sizeof(hModule), &cbReturned ))
  1330. { // get .exe name
  1331. szName[0] = 0;
  1332. GetModuleBaseName (hProcess, hModule, szName, MAX_PATH);
  1333. if ( 0 == _tcsicmp (szName, _T("mmc.exe")))
  1334. { // get all modules (.dlls)
  1335. lpMods = NULL;
  1336. iMods = GetModules (hProcess, &lpMods);
  1337. if (lpMods != NULL)
  1338. {
  1339. for (int j=1; !b && j<iMods; j++)
  1340. {
  1341. GetModuleBaseName (hProcess, lpMods[j], szName, MAX_PATH);
  1342. if (!_tcsicmp( szName, _T("Pop3Snap.dll") ) )
  1343. {
  1344. b = true;
  1345. }
  1346. }
  1347. }
  1348. free (lpMods);
  1349. }
  1350. }
  1351. if(b)
  1352. {
  1353. //This is mmc.exe with pop3snap.dll
  1354. TerminateProcess(hProcess, 0 );
  1355. b=FALSE;
  1356. }
  1357. CloseHandle( hProcess);
  1358. }
  1359. }
  1360. free (lpProcs);
  1361. return b;
  1362. }