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.

1069 lines
33 KiB

  1. // Notiflag.cpp : Defines the entry point for the application.
  2. //***********************************************************************
  3. // Reads a local XML file, hits the given url and gets back xml string
  4. // with another url, places an icon in system tray and links it to the url..
  5. // Copyright : Microsoft Corporation. PSSODEV team.
  6. //
  7. // Author : K J Babu (v-kjbad)
  8. // Pramod Walvekar (v-pramwa)
  9. //
  10. //***********************************************************************
  11. //includes
  12. #include "stdafx.h"
  13. #include "resource.h"
  14. #include "Notiflag.h"
  15. #include <crtdbg.h>
  16. //#define _WIN32_IE 0x0500
  17. #include <shellapi.h>
  18. #include <shlwapi.h>
  19. #include <wininet.h>
  20. #include <ole2.h>
  21. #include <initguid.h>
  22. #include <mstask.h>
  23. #include <wchar.h>
  24. #include <prsht.h>
  25. #include <MPC_main.h>
  26. //#include <atlbase.h> //defined in notiflag.h
  27. //#define WM_ICON WM_USER+333
  28. #define WM_ICON 0xBFFF
  29. #define ID_MYICON 5
  30. // Global Variables:
  31. HINSTANCE g_hInst; // current instance
  32. WCHAR szTitle[_MAX_PATH + 1]; // title bar text
  33. WCHAR szTaskName[_MAX_PATH + 1];
  34. WCHAR szWindowClass[_MAX_PATH + 1]; // window class name
  35. WCHAR szURL[_MAX_PATH + 1]; // URL to call if user clicks on the icon
  36. HRESULT hr = ERROR_SUCCESS;
  37. HWND g_Hwnd;
  38. //******************************************************************
  39. // Main function
  40. //
  41. // checks for the program instance
  42. // reads the client's incident list xml file
  43. // makes a call to remoteURL and reads the returned xml
  44. // adds program's executable path in the registry and
  45. // loads the icon in system area (tray)
  46. // waits for the single click on the icon and on single click
  47. // removes the entry from the registry, load the IE window with URL
  48. // and exits.
  49. //******************************************************************
  50. extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
  51. {
  52. MSG msg;
  53. int tmpDbgFlag;
  54. int nNumArgs = 0;
  55. LPCTSTR *cmdArgs = (LPCTSTR*)CommandLineToArgvW(GetCommandLineW(), &nNumArgs);
  56. #ifdef _DEBUG
  57. MessageBox(0, cmdArgs[0], L"app path", 0);
  58. #endif
  59. LoadString(hInstance, IDS_APP_TITLE, szTitle, _MAX_PATH);
  60. // check the previous instance of the program here
  61. // return if program is already running.
  62. HANDLE hMutex = CreateMutex(NULL,TRUE,szTitle);
  63. if(ERROR_ALREADY_EXISTS == GetLastError())
  64. return 0;
  65. /*
  66. * Set the debug-heap flag to keep freed blocks in the
  67. * heap's linked list - This will allow us to catch any
  68. * inadvertent use of freed memory
  69. */
  70. tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  71. tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  72. tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
  73. _CrtSetDbgFlag(tmpDbgFlag);
  74. // check if there are any command line parameters
  75. if (nNumArgs > 1)
  76. {
  77. // check if the first parameter is either /t or -t, which indicates AddNotiTask
  78. if((_tcscmp(cmdArgs[1], L"/t") == 0)||(_tcscmp(cmdArgs[1], L"-t") == 0))
  79. {
  80. // as first argument is /t or -t, run the AddNotiTask component
  81. hr = CallAddNotiTask(hInstance, cmdArgs, lpCmdLine);
  82. if(FAILED(hr))
  83. goto endMain;
  84. }
  85. }
  86. else
  87. {
  88. hr = CallNotiflag(hInstance);
  89. if(FAILED(hr))
  90. goto endMain;
  91. //*** change the priorty of the program
  92. SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
  93. // ***** All house keeping work done. start the program now...
  94. // Perform application initialization:
  95. if (!InitInstance (hInstance, nCmdShow))
  96. goto endMain;
  97. #ifdef _DEBUG
  98. MessageBox(0, L"Loading Icon...", L"NotiFlag: msg", 0);
  99. #endif
  100. // add the icon in system tray
  101. HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FLAGICON));
  102. if(hIcon != NULL)
  103. {
  104. BOOL bRet = MyTaskBarAddIcon(g_Hwnd, ID_MYICON, hIcon);
  105. DestroyIcon(hIcon);
  106. if (bRet == FALSE)// failed to create the system icon
  107. goto endMain;
  108. }
  109. #ifdef _DEBUG
  110. MessageBox(0, L"Icon loaded! waiting for click", L"NotiFlag: msg", 0);
  111. #endif
  112. // main message loop
  113. while (GetMessage(&msg, NULL, 0, 0))
  114. {
  115. TranslateMessage(&msg);
  116. DispatchMessage(&msg);
  117. }
  118. #ifdef _DEBUG
  119. MessageBox(0, L"closing NotiFlag program", L"NotiFlag: msg", 0);
  120. #endif
  121. // remove the icon from system tray and do other cleaning, exit.
  122. //
  123. }
  124. CloseHandle(hMutex);
  125. return (int)msg.wParam;
  126. endMain:
  127. CloseHandle(hMutex);
  128. return -1;
  129. }
  130. //*********************************************************************************
  131. // MyRegisterClass
  132. //
  133. // PURPOSE: Registers the window class.
  134. //*********************************************************************************
  135. ATOM MyRegisterClass(HINSTANCE hInstance)
  136. {
  137. USES_CONVERSION;
  138. WNDCLASSEX wcex;
  139. wcex.cbSize = sizeof(WNDCLASSEX);
  140. wcex.style = CS_HREDRAW | CS_VREDRAW;
  141. wcex.lpfnWndProc = (WNDPROC)WndProc;
  142. wcex.cbClsExtra = 0;
  143. wcex.cbWndExtra = 0;
  144. wcex.hInstance = hInstance;
  145. wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_FLAGICON);
  146. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  147. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  148. wcex.lpszMenuName = (LPCTSTR)IDC_NOTIFLAG;
  149. wcex.lpszClassName = szWindowClass;
  150. wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_FLAGICON );
  151. return RegisterClassEx(&wcex);
  152. }
  153. //*********************************************************************************
  154. // InitInstance(HANDLE, int)
  155. //
  156. // PURPOSE: Saves instance handle and creates main window
  157. //
  158. // COMMENTS:
  159. //
  160. // In this function, we save the instance handle in a global variable and
  161. // create and display the main program window.
  162. //*********************************************************************************
  163. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  164. {
  165. // create the window with no display
  166. g_Hwnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  167. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  168. return (g_Hwnd)?TRUE:FALSE;
  169. }
  170. //*********************************************************************************
  171. // WndProc(HWND, unsigned, WORD, LONG)
  172. //
  173. // PURPOSE: Processes messages for the main window.
  174. //
  175. // WM_COMMAND - process the application menu
  176. // WM_PAINT - Paint the main window
  177. // WM_DESTROY - post a quit message and return
  178. //*********************************************************************************
  179. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  180. {
  181. switch (message)
  182. {
  183. case WM_COMMAND:
  184. switch(LOWORD(wParam))
  185. {
  186. case IDC_DISABLE: // if user chose to disable task
  187. hr = DisableTask(); // disable the task
  188. if (FAILED(hr))
  189. #ifdef _DEBUG
  190. MessageBox(hWnd,L"Failed to disable task",L"PSSIncidentNotification",MB_OK);
  191. #endif
  192. MyTaskBarDeleteIcon(g_Hwnd,ID_MYICON); // remove icon from tray
  193. DestroyWindow(g_Hwnd); // end application
  194. break;
  195. case IDC_SETFREQUENCY: // if user chose to change the frequency of the task
  196. hr = EditTask(); // display task schedule settings so user can change it
  197. if (FAILED(hr))
  198. #ifdef _DEBUG
  199. MessageBox(hWnd,L"No Changes in task",L"PSSIncidentNotification",MB_OK);
  200. #endif
  201. break;
  202. default:
  203. break;
  204. }
  205. break;
  206. case WM_ICON:
  207. {
  208. if ((UINT)lParam == WM_LBUTTONDOWN)
  209. {
  210. // Show new Browser window with the given URL
  211. ShellExecute(g_Hwnd, L"open", szURL, NULL, NULL, SW_SHOWNORMAL);
  212. MyTaskBarDeleteIcon(g_Hwnd,ID_MYICON);
  213. DestroyWindow(g_Hwnd);
  214. }
  215. //if(((UINT)lParam == 0x204) || ((UINT)lParam == 0x205))
  216. if ((UINT)lParam == WM_RBUTTONDOWN) // if user clicks right button
  217. {
  218. POINT sPoint;
  219. HMENU hMenu=LoadMenu(g_hInst,MAKEINTRESOURCE(IDC_NOTIFLAG)); // load menu
  220. if(hMenu!=NULL)
  221. {
  222. HMENU hSubMenu=GetSubMenu(hMenu,0);
  223. GetCursorPos(&sPoint); // get location of mouse
  224. SetForegroundWindow(hWnd);
  225. TrackPopupMenu(hSubMenu,TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RIGHTBUTTON ,sPoint.x,sPoint.y,0,hWnd,NULL); // track the menu
  226. PostMessage(hWnd, WM_NULL, 0, 0);
  227. DestroyMenu(hMenu);
  228. }
  229. }
  230. break;
  231. }
  232. case WM_DESTROY:
  233. PostQuitMessage(0);
  234. break;
  235. default:
  236. return DefWindowProc(hWnd, message, wParam, lParam);
  237. }
  238. return 0;
  239. }
  240. //****************************************************************************
  241. // MyTaskBarAddIcon
  242. //
  243. // adds an icon to system tray.
  244. // Returns : TRUE if successful, or FALSE otherwise.
  245. //****************************************************************************
  246. BOOL MyTaskBarAddIcon(HWND hwnd, UINT uID, HICON hicon)
  247. {
  248. NOTIFYICONDATA tnid={0};
  249. // Find out what version of the shell we are using for tray icon stuff
  250. HINSTANCE hShellDll;
  251. DLLGETVERSIONPROC pDllGetVersion;
  252. DLLVERSIONINFO dvi;
  253. BOOL bUseTrayBalloon = FALSE;
  254. // balloon tooltip is supported only in shell32.dll 5.0, so check the version
  255. hShellDll = LoadLibrary(L"Shell32.dll");
  256. if(hShellDll != NULL)
  257. {
  258. // enable balloon tooltip if IE version is greater than 5
  259. pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hShellDll, "DllGetVersion");
  260. dvi.cbSize = sizeof(dvi);
  261. if(pDllGetVersion != NULL && SUCCEEDED((*pDllGetVersion)(&dvi)))
  262. if(dvi.dwMajorVersion >= 5) bUseTrayBalloon = TRUE;
  263. FreeLibrary(hShellDll);
  264. }
  265. //fill icon structure
  266. tnid.cbSize = sizeof(NOTIFYICONDATA);
  267. tnid.hWnd = hwnd;
  268. tnid.uID = uID;
  269. tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  270. tnid.uCallbackMessage = WM_ICON;
  271. tnid.hIcon = hicon;
  272. LoadString(g_hInst, IDS_TOOLTIP, tnid.szTip, MAXSTRLEN(tnid.szTip));
  273. if (bUseTrayBalloon) // if IE version supports this then...
  274. {
  275. tnid.uFlags |= NIF_INFO;
  276. tnid.uTimeout = 60000; // in milliseconds
  277. tnid.dwInfoFlags = NIIF_INFO;
  278. LoadString(g_hInst, IDS_BALLOONTITLE, tnid.szInfoTitle, MAXSTRLEN(tnid.szInfoTitle));
  279. LoadString(g_hInst, IDS_BALLOONTIP, tnid.szInfo, MAXSTRLEN(tnid.szInfo));
  280. }
  281. return Shell_NotifyIcon(NIM_ADD, &tnid);
  282. }
  283. //****************************************************************************
  284. // MyTaskBarDeleteIcon
  285. //
  286. // deletes an icon from the taskbar status area.
  287. // Returns : TRUE if successful, or FALSE otherwise.
  288. //****************************************************************************
  289. BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID)
  290. {
  291. NOTIFYICONDATA tnid;
  292. tnid.cbSize = sizeof(NOTIFYICONDATA);
  293. tnid.hWnd = hwnd;
  294. tnid.uID = uID;
  295. return Shell_NotifyIcon(NIM_DELETE, &tnid);
  296. }
  297. //****************************************************************************
  298. // LoadThisXml
  299. //
  300. // Load the given file in XMLDOM object and returns that pointer
  301. // Returns : XMLDom pointer
  302. //***************************************************************************
  303. CComPtr<IXMLDOMDocument> LoadThisXml(const WCHAR *csFileName)
  304. {
  305. // get smart pointer to IXMLDOMDocument interface
  306. CComPtr<IXMLDOMDocument> pXmlDoc;
  307. VARIANT vFile;
  308. CComVariant vtest;
  309. VARIANT_BOOL vb=1;
  310. HRESULT hr;
  311. CComBSTR bstrVal(csFileName); // this has the output file
  312. //initialize the variant
  313. VariantInit(&vFile);
  314. vFile.vt = VT_BSTR; //specify that it contains a string
  315. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXmlDoc);
  316. if (FAILED(hr))
  317. return NULL;
  318. //increase ref count, else pointer will be released twice before CoUnInitialize() and
  319. // will throw exception
  320. pXmlDoc.p->AddRef();
  321. V_BSTR(&vFile) = bstrVal;
  322. pXmlDoc->put_async(VARIANT_FALSE);
  323. hr = pXmlDoc->load(vFile, &vb);
  324. if (FAILED (hr) || vb == 0)
  325. return NULL;
  326. VariantClear(&vFile);
  327. return pXmlDoc;
  328. }
  329. //****************************************************************************
  330. // LoadHTTPRequestXml
  331. //
  332. // Makes the request to the asp page and gets the XML out of Response.
  333. // Returns : XMLDom pointer
  334. //****************************************************************************
  335. CComPtr<IXMLDOMDocument> LoadHTTPRequestXml(WCHAR *csURL, CComPtr<IXMLDOMDocument> pDoc)
  336. {
  337. CComPtr<IXMLDOMDocument> pXmlDoc;
  338. CComPtr<IXMLHttpRequest> pRequest;
  339. CComPtr<IDispatch> pDispRes;
  340. CComPtr<IDispatch> pDisp;
  341. HRESULT hr;
  342. // create an instance of XMLHTTPRequest and open the connection
  343. hr = CoCreateInstance(CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER, IID_IXMLHttpRequest, (void**)&pRequest);
  344. if (FAILED(hr))
  345. goto endRequestXml;
  346. //hr = pRequest->open(CComBSTR(L("POST")), CComBSTR(csURL), _variantL(VARIANT_FALSE));
  347. hr = pRequest->open( CComBSTR( L"POST" ), CComBSTR( csURL ), CComVariant(VARIANT_FALSE), CComVariant(), CComVariant());
  348. if(FAILED(hr))
  349. goto endRequestXml;
  350. hr = pRequest->setRequestHeader(CComBSTR(L"ACCEPT_LANGUAGE"),CComBSTR(L"en-us"));
  351. if(FAILED(hr))
  352. goto endRequestXml;
  353. // send the xml now. Get the Dispatch pointer of XML
  354. hr = pDoc->QueryInterface(IID_IDispatch, (void **)&pDisp);
  355. if (FAILED(hr))
  356. goto endRequestXml;
  357. #ifdef _DEBUG
  358. MessageBox(0, L"calling send", L"NotiFlag: LoadHTTPRequestXml", 0);
  359. #endif
  360. // call send
  361. VARIANT varDisp;
  362. varDisp.vt = VT_DISPATCH;
  363. varDisp.pdispVal = pDisp;
  364. hr = pRequest->send(varDisp);
  365. if (FAILED(hr))
  366. goto endRequestXml;
  367. VariantClear(&varDisp);
  368. #ifdef _DEBUG
  369. MessageBox(0, L"calling getxmlresponse", L"NotiFlag: LoadHTTPRequestXml", 0);
  370. #endif
  371. // Read the response
  372. hr = pRequest->get_responseXML(&pDispRes);
  373. if (FAILED(hr))
  374. goto endRequestXml;
  375. // get the XMLDom pointer from iDispatch
  376. hr = pDispRes->QueryInterface(IID_IXMLDOMDocument, (void **)&pXmlDoc);
  377. if (FAILED(hr))
  378. goto endRequestXml;
  379. return pXmlDoc;
  380. endRequestXml:
  381. return NULL;
  382. }
  383. //***********************************************************************************
  384. // GetNodeValue
  385. //
  386. // Reads the node value from the given XMLDOMDocument and copies into csValue.
  387. // Returns : 0 = success & -ve = error.
  388. //***********************************************************************************
  389. int GetNodeValue(CComPtr<IXMLDOMDocument> pXmlDoc,const WCHAR *csNode, WCHAR *csValue)
  390. {
  391. CComPtr<IXMLDOMNode> pNode;
  392. CComBSTR bstrIdValue(csNode);
  393. CComVariant vIdValue;
  394. HRESULT hr;
  395. // get to the node
  396. hr = pXmlDoc->selectSingleNode(bstrIdValue, &pNode);
  397. if (FAILED(hr) || pNode == NULL)
  398. return -1;
  399. // read the value of the specified tag
  400. hr = pNode->get_nodeValue(&vIdValue);
  401. if (FAILED(hr))
  402. return -1;
  403. {
  404. USES_CONVERSION;
  405. wcscpy( csValue, vIdValue.bstrVal );
  406. }
  407. return 0;
  408. }
  409. //***********************************************************************************
  410. // CallNotiflag
  411. //
  412. // Loads local xml file and extracts url from it, hits the url, retrieves xml string
  413. // Loads the retrieved xml string, checks a few conditions and if met,
  414. // loads an icon in the system tray and when the user clicks on the icon,
  415. // it takes him to that url in the HSS browser
  416. // Returns : S_OK for success, E_FAIL for failure
  417. //***********************************************************************************
  418. HRESULT CallNotiflag(HINSTANCE hInstance)
  419. {
  420. #ifdef _DEBUG
  421. MessageBox(0, L"Notiflag is active", L"Active", 0);
  422. #endif
  423. // Initialize global strings
  424. LoadString(hInstance, IDS_APP_TITLE, szTitle, _MAX_PATH);
  425. LoadString(hInstance, IDC_NOTIFLAG, szWindowClass, _MAX_PATH);
  426. MyRegisterClass(hInstance);
  427. hr = CoInitialize(NULL);
  428. if (FAILED(hr))
  429. goto endNoti;
  430. {
  431. //*** to read the xml file info
  432. //declare smart pointers to XMLDOMDocument Interface
  433. CComPtr<IXMLDOMDocument> pSvrXmlDoc;
  434. CComPtr<IXMLDOMDocument> pUserXmlDoc;
  435. //string variables to hold xml file path and node text
  436. WCHAR csXmlFilePath[_MAX_PATH + 1];
  437. WCHAR csUserXmlFile[_MAX_PATH + 1];
  438. WCHAR csNode[_MAX_PATH + 1];
  439. WCHAR csValue[1024];
  440. WCHAR csUserProfile[_MAX_PATH + 1];
  441. csValue[0] = '\0';
  442. // get the user profile path
  443. LoadString(hInstance, IDS_USERPROFILE, csUserProfile, _MAX_PATH);
  444. GetEnvironmentVariable(csUserProfile, csUserXmlFile, _MAX_PATH);
  445. //concatenate the xml file name to the profile path
  446. LoadString(hInstance, IDS_XMLFILEPATH, csXmlFilePath, _MAX_PATH);
  447. _tcscat(csUserXmlFile, csXmlFilePath);
  448. #ifdef _DEBUG
  449. MessageBox(0, csUserXmlFile, L"NotiFlag: client xml", 0);
  450. #endif
  451. // load this xml file
  452. if ((pUserXmlDoc = LoadThisXml(csUserXmlFile)) == NULL)
  453. goto endNoti;
  454. //get the value of the node "IncidentID"
  455. LoadString(hInstance, IDS_INCIDENTID, csNode, _MAX_PATH);
  456. if (GetNodeValue(pUserXmlDoc, csNode, csValue))
  457. goto endNoti;
  458. if (csValue[0] != '\0')
  459. {
  460. //get the value of the node "RemoteURL"
  461. LoadString(hInstance, IDS_REMOTEURL, csNode, _MAX_PATH);
  462. if (GetNodeValue(pUserXmlDoc, csNode, csValue))
  463. goto endNoti;
  464. }
  465. #ifdef _DEBUG
  466. MessageBox(0, L"calling the asp file", L"NotiFlag: msg", 0);
  467. #endif
  468. // load the server ASP page and load returned XML string in XMLDOM
  469. if ((pSvrXmlDoc = LoadHTTPRequestXml(csValue, pUserXmlDoc)) == NULL)
  470. goto endNoti;
  471. _tcscpy(csValue, L"\0");
  472. //get the value of the node "ResponseCount"
  473. LoadString(hInstance, IDS_RESPONSECOUNT, csNode, _MAX_PATH);
  474. if (GetNodeValue(pSvrXmlDoc, csNode, csValue))
  475. goto endNoti;
  476. if ((atoi((const char *)csValue)) <= 0)
  477. goto endNoti;
  478. // else proceed
  479. #ifdef _DEBUG
  480. MessageBox(0, L"reading values", L"NotiFlag: main", 0);
  481. #endif
  482. // load the URL to hit
  483. LoadString(hInstance, IDS_LOCATIONTOHIT, csNode, _MAX_PATH);
  484. if (GetNodeValue(pSvrXmlDoc, csNode, szURL) || szURL == NULL)
  485. goto endNoti;
  486. // load the serverdatetime
  487. LoadString(hInstance, IDS_SERVERDATETIME, csNode, _MAX_PATH);
  488. if (GetNodeValue(pSvrXmlDoc, csNode, csValue))
  489. goto endNoti;
  490. #ifdef _DEBUG
  491. MessageBox(0, L"putting date and saving client xml", L"NotiFlag: main", 0);
  492. #endif
  493. }
  494. //Close the COM library and release resources
  495. CoUninitialize();
  496. return hr=S_OK;
  497. endNoti:
  498. CoUninitialize();
  499. return hr=E_FAIL;
  500. }
  501. //***********************************************************************************
  502. // CallAddNotiTask
  503. //
  504. // Creates a new task in the scheduler
  505. // Returns : S_OK for success, E_FAIL for failure
  506. //***********************************************************************************
  507. HRESULT CallAddNotiTask(HINSTANCE hInstance, LPCTSTR *cmdArgs,LPTSTR lpCmdLine)
  508. {
  509. #ifdef _DEBUG
  510. MessageBox(0, L"AddNotiTask is Active", L"Active", 0);
  511. MessageBox(0, cmdArgs[1], L"First argument", 0);
  512. #endif
  513. hr = CoInitialize(NULL);
  514. if (FAILED(hr))
  515. goto endAddNotiTask;
  516. {
  517. // smart interface pointers
  518. CComPtr<ITaskScheduler> pITS;
  519. CComPtr<IUnknown> pITaskUnknown;
  520. CComPtr<IScheduledWorkItem> pIScheduledWorkItem;
  521. CComPtr<ITaskTrigger> pITaskTrigger;
  522. CComPtr<ITask> pITask;
  523. CComBSTR bstrAccName(lpCmdLine);
  524. CComBSTR bstrVal;
  525. WCHAR szUserName[_MAX_PATH + 1];
  526. WCHAR szRegEntry[_MAX_PATH + 1];
  527. DWORD cchUserName = MAXSTRLEN(szUserName);
  528. if ( !GetUserName( szUserName, &cchUserName ) )
  529. goto endAddNotiTask;
  530. BOOL bTaskExists=FALSE;
  531. // Create a Task Schedular object ...
  532. hr = CoCreateInstance(CLSID_CTaskScheduler,
  533. NULL,
  534. CLSCTX_INPROC_SERVER,
  535. IID_ITaskScheduler,
  536. (void **) &pITS);
  537. if (FAILED(hr))
  538. goto endAddNotiTask;
  539. ////////////////////////////////////////////////////////
  540. // Check/Create a work item/Task
  541. ////////////////////////////////////////////////////////
  542. LoadString(hInstance, IDS_TASKNAME, szTaskName, _MAX_PATH);
  543. // check if the work item already exists
  544. if(SUCCEEDED(pITS->Activate((LPCWSTR)szTaskName, IID_ITask, &pITaskUnknown)))
  545. {
  546. bTaskExists = TRUE;
  547. hr = pITaskUnknown.QueryInterface(&pITask);
  548. goto endAddNotiTask;
  549. }
  550. else
  551. {
  552. // create a new work item
  553. hr = pITS->NewWorkItem(szTaskName, // Name of task
  554. CLSID_CTask, // Class identifier
  555. IID_ITask, // Interface identifier
  556. (IUnknown**)&pITask); // Address of task interface
  557. }
  558. if (FAILED(hr))
  559. goto endAddNotiTask;
  560. // set the account information
  561. hr = pITask->QueryInterface(IID_IScheduledWorkItem, (void**)&pIScheduledWorkItem);
  562. if (FAILED(hr) || pIScheduledWorkItem==NULL)
  563. goto endAddNotiTask;
  564. hr = pIScheduledWorkItem->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON|TASK_FLAG_INTERACTIVE); // TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
  565. if (FAILED(hr))
  566. goto endAddNotiTask;
  567. hr = pIScheduledWorkItem->SetAccountInformation((LPCWSTR)szUserName, NULL);
  568. if (FAILED(hr))
  569. goto endAddNotiTask;
  570. // get the exe path ...
  571. {
  572. bstrVal = cmdArgs[0];
  573. hr = pITask->SetApplicationName(bstrVal);
  574. if (FAILED (hr))
  575. goto endAddNotiTask;
  576. }
  577. ///////////////////////////////////////////////////////////////////
  578. // Define TASK_TRIGGER structure.
  579. // Check/Create the new trigger.
  580. ///////////////////////////////////////////////////////////////////
  581. TASK_TRIGGER pTrigger;
  582. ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));
  583. pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);
  584. if (bTaskExists)
  585. {
  586. hr = pIScheduledWorkItem->GetTrigger(0, &pITaskTrigger);
  587. if (FAILED(hr) || pITaskTrigger == NULL)
  588. goto endAddNotiTask;
  589. hr = pITaskTrigger->GetTrigger(&pTrigger);
  590. if (FAILED(hr))
  591. goto endAddNotiTask;
  592. }
  593. else
  594. {
  595. WORD piNewTrigger;
  596. hr = pIScheduledWorkItem->CreateTrigger(&piNewTrigger, &pITaskTrigger);
  597. if (FAILED(hr))
  598. goto endAddNotiTask;
  599. }
  600. if (FAILED(hr) || pITaskTrigger == NULL)
  601. goto endAddNotiTask;
  602. // add the entry in the registry
  603. {
  604. TCHAR szExePath[_MAX_PATH + 1];
  605. HKEY hKey;
  606. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\PSS\\Notification", 0, KEY_ALL_ACCESS, &hKey))
  607. {
  608. #ifdef _DEBUG
  609. MessageBox(0, L"no registry entry", L"notitask", 0);
  610. #endif
  611. // if key doesnt exist, use default values
  612. pTrigger.wStartHour = 2; // start from the 1st hour
  613. pTrigger.wStartMinute = 0;
  614. pTrigger.MinutesDuration = 1440; // for 24 hours
  615. pTrigger.MinutesInterval = 15; // every 1 hour
  616. // Note that wBeginDay, wBeginMonth, and wBeginYear must
  617. // be set to a valid day, month, and year respectively.
  618. pTrigger.wBeginDay = 1; // Required - 1st
  619. pTrigger.wBeginMonth = 12; // Required - December
  620. pTrigger.wBeginYear = 2000; // Required - 2000
  621. }
  622. else
  623. {
  624. #ifdef _DEBUG
  625. MessageBox(0, L"registry entry exists", L"notitask", 0);
  626. #endif
  627. // if key exists, read from registry
  628. DWORD lpType = 4; // type buffer
  629. DWORD lpData=0; // data buffer
  630. DWORD lpcbData=sizeof(DWORD); // size of data buffer
  631. LoadString(NULL, IDS_WSTARTHOUR, szRegEntry, _MAX_PATH);
  632. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (LPBYTE)&lpData, &lpcbData ))
  633. return -1;
  634. pTrigger.wStartHour = (WORD)lpData; // start from the 1st hour
  635. LoadString(NULL, IDS_WSTARTMINUTE, szRegEntry, _MAX_PATH);
  636. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (LPBYTE)&lpData, &lpcbData ))
  637. return -1;
  638. pTrigger.wStartMinute = (WORD)lpData;
  639. LoadString(NULL, IDS_MINUTESDURATION, szRegEntry, _MAX_PATH);
  640. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (LPBYTE)&lpData, &lpcbData ))
  641. return -1;
  642. pTrigger.MinutesDuration = (WORD)lpData; // for 24 hours
  643. LoadString(NULL, IDS_FREQUENCY, szRegEntry, _MAX_PATH);
  644. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (BYTE *)&lpData, &lpcbData ))
  645. return -1;
  646. pTrigger.MinutesInterval = (WORD)lpData; // for 24 hours
  647. LoadString(NULL, IDS_WBEGINDAY, szRegEntry, _MAX_PATH);
  648. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (BYTE *)&lpData, &lpcbData ))
  649. return -1;
  650. pTrigger.wBeginDay = (WORD)lpData; // date of the month
  651. LoadString(NULL, IDS_WBEGINMONTH, szRegEntry, _MAX_PATH);
  652. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (BYTE *)&lpData, &lpcbData ))
  653. return -1;
  654. pTrigger.wBeginMonth = (WORD)lpData; // month
  655. LoadString(NULL, IDS_WBEGINYEAR, szRegEntry, _MAX_PATH);
  656. if (ERROR_SUCCESS != RegQueryValueEx(hKey, szRegEntry,0, &lpType, (BYTE *)&lpData, &lpcbData ))
  657. return -1;
  658. pTrigger.wBeginYear = (WORD)lpData; // year
  659. }
  660. pTrigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
  661. pTrigger.Type.Daily.DaysInterval = 1; // daily!!
  662. // get the application's executable path
  663. ::GetModuleFileName(hInstance, szExePath, _MAX_PATH);
  664. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\PSS\\Notification", 0, KEY_ALL_ACCESS, &hKey))
  665. {
  666. DWORD dwDisposition;
  667. DWORD szwStartHour = 1;
  668. DWORD szwStartMinute = 0;
  669. DWORD szMinutesDuration=1440;
  670. DWORD szMinutesInterval =15;
  671. DWORD szwBeginDay = 1;
  672. DWORD szwBeginMonth = 12;
  673. DWORD szwBeginYear = 2000;
  674. LoadString(NULL, IDS_REGKEY, szRegEntry, _MAX_PATH);
  675. if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, szRegEntry, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisposition))
  676. return -1;
  677. LoadString(NULL, IDS_WSTARTHOUR, szRegEntry, _MAX_PATH);
  678. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwStartHour, sizeof(szwStartHour)))
  679. return -1;
  680. LoadString(NULL, IDS_WSTARTMINUTE, szRegEntry, _MAX_PATH);
  681. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwStartMinute, sizeof(szwStartMinute)))
  682. return -1;
  683. LoadString(NULL, IDS_MINUTESDURATION, szRegEntry, _MAX_PATH);
  684. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szMinutesDuration, sizeof(szMinutesDuration)))
  685. return -1;
  686. LoadString(NULL, IDS_FREQUENCY, szRegEntry, _MAX_PATH);
  687. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szMinutesInterval, sizeof(szMinutesInterval)))
  688. return -1;
  689. LoadString(NULL, IDS_WBEGINDAY, szRegEntry, _MAX_PATH);
  690. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginDay, sizeof(szwBeginDay)))
  691. return -1;
  692. LoadString(NULL, IDS_WBEGINMONTH, szRegEntry, _MAX_PATH);
  693. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginMonth, sizeof(szwBeginMonth)))
  694. return -1;
  695. LoadString(NULL, IDS_WBEGINYEAR, szRegEntry, _MAX_PATH);
  696. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginYear, sizeof(szwBeginYear)))
  697. return -1;
  698. }
  699. RegCloseKey(hKey);
  700. }
  701. // Call ITaskTrigger::SetTrigger to set trigger criteria.
  702. hr = pITaskTrigger->SetTrigger (&pTrigger);
  703. if (FAILED(hr))
  704. goto endAddNotiTask;
  705. /////////////////////////////////////////////////////////////////
  706. // Call IUnknown::QueryInterface to get a pointer to
  707. // IPersistFile and IPersistFile::Save to save
  708. // the new task to disk.
  709. /////////////////////////////////////////////////////////////////
  710. CComPtr<IPersistFile> pIPersistFile;
  711. hr = pITask->QueryInterface(IID_IPersistFile,
  712. (void **)&pIPersistFile);
  713. if (FAILED(hr) || pIPersistFile == NULL)
  714. goto endAddNotiTask;
  715. hr = pIPersistFile->Save(NULL, FALSE);
  716. if (FAILED(hr))
  717. goto endAddNotiTask;
  718. }
  719. CoUninitialize();
  720. return hr = S_OK;
  721. endAddNotiTask:
  722. CoUninitialize();
  723. return hr=E_FAIL;
  724. }
  725. HRESULT DisableTask()
  726. {
  727. hr = CoInitialize(NULL);
  728. if (FAILED(hr))
  729. goto endDisable;
  730. {
  731. CComPtr<ITaskScheduler> pITS;
  732. CComPtr<IUnknown> pITaskUnknown;
  733. CComPtr<IScheduledWorkItem> pIScheduledWorkItem;
  734. CComPtr<ITaskTrigger> pITaskTrigger;
  735. CComPtr<ITask> pITask;
  736. WCHAR szUserName[_MAX_PATH + 1];
  737. DWORD cchUserName = MAXSTRLEN(szUserName);
  738. if ( !GetUserName( szUserName, &cchUserName ) )
  739. goto endDisable;
  740. hr = CoCreateInstance(CLSID_CTaskScheduler,
  741. NULL,
  742. CLSCTX_INPROC_SERVER,
  743. IID_ITaskScheduler,
  744. (void **) &pITS);
  745. if (FAILED(hr))
  746. goto endDisable;
  747. LoadString(NULL, IDS_TASKNAME, szTaskName, _MAX_PATH);
  748. if(SUCCEEDED(pITS->Activate((LPCWSTR)szTaskName, IID_ITask, &pITaskUnknown)))
  749. {
  750. hr = pITaskUnknown.QueryInterface(&pITask);
  751. if (FAILED(hr))
  752. goto endDisable;
  753. }
  754. hr = pITask->QueryInterface(IID_IScheduledWorkItem, (void**)&pIScheduledWorkItem);
  755. if (FAILED(hr) || pIScheduledWorkItem==NULL)
  756. goto endDisable;
  757. //set the flags to disable the task
  758. hr = pIScheduledWorkItem->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON|TASK_FLAG_INTERACTIVE|TASK_FLAG_DISABLED); // TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
  759. if (FAILED(hr))
  760. goto endDisable;
  761. // set the account information
  762. hr = pIScheduledWorkItem->SetAccountInformation((LPCWSTR)szUserName, NULL);
  763. if (FAILED(hr))
  764. goto endDisable;
  765. /////////////////////////////////////////////////////////////////
  766. // Call IUnknown::QueryInterface to get a pointer to
  767. // IPersistFile and IPersistFile::Save to save
  768. // the new task to disk.
  769. /////////////////////////////////////////////////////////////////
  770. CComPtr<IPersistFile> pIPersistFile;
  771. hr = pITask->QueryInterface(IID_IPersistFile,
  772. (void **)&pIPersistFile);
  773. if (FAILED(hr) || pIPersistFile == NULL)
  774. goto endDisable;
  775. hr = pIPersistFile->Save(NULL, FALSE);
  776. if (FAILED(hr))
  777. goto endDisable;
  778. }
  779. CoUninitialize();
  780. return hr=S_OK;
  781. endDisable:
  782. CoUninitialize();
  783. return hr=E_FAIL;
  784. }
  785. HRESULT EditTask()
  786. {
  787. hr = CoInitialize(NULL);
  788. if (FAILED(hr))
  789. goto endEdit;
  790. {
  791. CComPtr<ITaskScheduler> pITS;
  792. CComPtr<ITask> pITask;
  793. CComPtr<ITaskTrigger> pITaskTrigger;
  794. hr = CoCreateInstance(CLSID_CTaskScheduler,
  795. NULL,
  796. CLSCTX_INPROC_SERVER,
  797. IID_ITaskScheduler,
  798. (void **) &pITS);
  799. if (FAILED(hr))
  800. goto endEdit;
  801. LoadString(NULL, IDS_TASKNAME, szTaskName, _MAX_PATH);
  802. hr = pITS->Activate(szTaskName,
  803. IID_ITask,
  804. (IUnknown**) &pITask);
  805. if (FAILED(hr))
  806. goto endEdit;
  807. ///////////////////////////////////////////////////////////////////
  808. // Call ITask::QueryInterface to retrieve the IProvideTaskPage
  809. // interface, and call IProvideTaskPage::GetPage to retrieve the
  810. // task page.
  811. ///////////////////////////////////////////////////////////////////
  812. TASKPAGE tpType = TASKPAGE_SCHEDULE;
  813. BOOL fPersistChanges = TRUE;
  814. HPROPSHEETPAGE phPage;
  815. CComPtr<IProvideTaskPage> pIProvTaskPage;
  816. hr = pITask->QueryInterface(IID_IProvideTaskPage,
  817. (void **)&pIProvTaskPage);
  818. if (FAILED(hr))
  819. goto endEdit;
  820. hr = pIProvTaskPage->GetPage(tpType,
  821. fPersistChanges,
  822. &phPage);
  823. if (FAILED(hr))
  824. goto endEdit;
  825. //////////////////////////////////////////////////////////////////
  826. // Display the page using additional code
  827. //////////////////////////////////////////////////////////////////
  828. PROPSHEETHEADER psh;
  829. ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
  830. psh.dwSize = sizeof(PROPSHEETHEADER);
  831. psh.dwFlags = PSH_DEFAULT | PSH_NOAPPLYNOW;
  832. psh.phpage = &phPage;
  833. psh.nPages = 1;
  834. INT_PTR psResult = PropertySheet(&psh);
  835. if (psResult <= 0)
  836. goto endEdit;
  837. ///////////////////////////////////////////////////////////////////
  838. // Define TASK_TRIGGER structure.
  839. // Check/Create the new trigger.
  840. ///////////////////////////////////////////////////////////////////
  841. TASK_TRIGGER pTrigger;
  842. ZeroMemory(&pTrigger, sizeof (TASK_TRIGGER));
  843. pTrigger.cbTriggerSize = sizeof (TASK_TRIGGER);
  844. hr = pITask->GetTrigger(0, &pITaskTrigger);
  845. if (FAILED(hr) || pITaskTrigger == NULL)
  846. goto endEdit;
  847. hr = pITaskTrigger->GetTrigger(&pTrigger);
  848. if (FAILED(hr))
  849. goto endEdit;
  850. // add the entry in the registry
  851. {
  852. DWORD szwStartHour = 1;
  853. DWORD szwStartMinute = 0;
  854. DWORD szMinutesDuration = 1440;
  855. DWORD szMinutesInterval =15;
  856. DWORD szwBeginDay = 1;
  857. DWORD szwBeginMonth = 12;
  858. DWORD szwBeginYear = 2000;
  859. WCHAR szRegEntry[_MAX_PATH + 1];
  860. HKEY hKey;
  861. szwStartHour = pTrigger.wStartHour;
  862. szwStartMinute = pTrigger.wStartMinute;
  863. szMinutesInterval = pTrigger.MinutesInterval;
  864. szMinutesDuration = pTrigger.MinutesDuration;
  865. szwBeginDay = pTrigger.wBeginDay;
  866. szwBeginMonth = pTrigger.wBeginMonth;
  867. szwBeginYear = pTrigger.wBeginYear;
  868. LoadString(NULL, IDS_REGKEY, szRegEntry, _MAX_PATH);
  869. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szRegEntry, 0, KEY_ALL_ACCESS, &hKey))
  870. {
  871. LoadString(NULL, IDS_WSTARTHOUR, szRegEntry, _MAX_PATH);
  872. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwStartHour, sizeof(szwStartHour)))
  873. goto endEdit;
  874. LoadString(NULL, IDS_WSTARTMINUTE, szRegEntry, _MAX_PATH);
  875. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwStartMinute, sizeof(szwStartMinute)))
  876. goto endEdit;
  877. LoadString(NULL, IDS_MINUTESDURATION, szRegEntry, _MAX_PATH);
  878. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szMinutesDuration, sizeof(szMinutesDuration)))
  879. goto endEdit;
  880. LoadString(NULL, IDS_FREQUENCY, szRegEntry, _MAX_PATH);
  881. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szMinutesInterval, sizeof(szMinutesInterval)))
  882. goto endEdit;
  883. LoadString(NULL, IDS_WBEGINDAY, szRegEntry, _MAX_PATH);
  884. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginDay, sizeof(szwBeginDay)))
  885. goto endEdit;
  886. LoadString(NULL, IDS_WBEGINMONTH, szRegEntry, _MAX_PATH);
  887. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginMonth, sizeof(szwBeginMonth)))
  888. goto endEdit;
  889. LoadString(NULL, IDS_WBEGINYEAR, szRegEntry, _MAX_PATH);
  890. if (ERROR_SUCCESS != RegSetValueEx(hKey, szRegEntry, 0, REG_DWORD, (const BYTE *)&szwBeginYear, sizeof(szwBeginYear)))
  891. goto endEdit;
  892. }
  893. RegCloseKey(hKey);
  894. }
  895. }
  896. CoUninitialize();
  897. return hr=S_OK;
  898. endEdit:
  899. CoUninitialize();
  900. return hr=E_FAIL;
  901. }