Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 894
  • Last Modified:

Shell_NotifyIcon fails with ERROR_FILE_NOT_FOUND on Vista Beta II

Hi all. We are in the process of testing our application on Windows Vista Beta II to find portability issues. The program is a Windows Service that runs with the System Account user and has access to the desktop. When the service tries to install its icon in the Notification Area, the Shell_NotifyIcon function fails with ERROR_FILE_NOT_FOUND.

I know Vista has increased security compared to XP, and I'm pretty sure it has something to do with it. The only solution I came up with is to make another program that handles the tray messages and dispatches the commands to the service thru a named pipe. I would like to avoid this solution if possible.

Here's the code I use :

// test_tray.cpp
//
#include "stdafx.h"
#include "shellapi.h"
#include "resource.h"
#include "ntservice.h"
#include <misc/trace.h>

#define SERVICE_NAME                "CRAService"

using namespace TELUS::Angel::Misc;

PROG_USE_TRACE("tray_tester");
bool  RegisterWindow();
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
void WINAPI Run(DWORD argc, char* argv[]);
HWND                              ghWnd = NULL;

NtService               gobjService;
UINT                              gMsg = 0;

void WINAPI Run(DWORD argc, char* argv[])
{
      FUNC_USE_TRACE("main");
      NOTIFYICONDATA            mNiData = {0};
      bool                              isSuccess = false;

      TRACE_INIT_PROCESS("C:\\tray_tester.log", Trace::FullTrace);
      TRACE_START();

      gobjService.resgister(SERVICE_NAME);
   gobjService.setStatus(SERVICE_START_PENDING, 0, 30);
      gobjService.setStatus(SERVICE_RUNNING);

      gMsg = RegisterWindowMessage("AlsNotifyCommand");
      if (!gMsg)
      {
            TRACE_SYS_CALL("RegisterWindowMessage");
      }
      // Create the Msg Window
      if (isSuccess = RegisterWindow())
      {
            ghWnd = CreateWindow("AlsMsgWndClass", "", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
            isSuccess = ghWnd != NULL;
            if (!isSuccess)
            {
                  TRACE_SYS_CALL("CreateWindow");
            }
      }
      
      // Add Tray Icon
      if (isSuccess)
      {
            mNiData.cbSize = sizeof(NOTIFYICONDATA);
            mNiData.uID = IDI_NOTIFY_ICON;
            mNiData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
            mNiData.hIcon =
                  (HICON)LoadImage( GetModuleHandle(NULL),
                              MAKEINTRESOURCE(IDI_NOTIFY_ICON),
                              IMAGE_ICON,
                              GetSystemMetrics(SM_CXSMICON),
                              GetSystemMetrics(SM_CYSMICON),
                              LR_DEFAULTCOLOR);

            if (!mNiData.hIcon)
            {
                  TRACE_SYS_CALL("LoadImage");
            }
            strcpy(mNiData.szTip, "test tip");
            mNiData.hWnd = ghWnd;
            mNiData.uCallbackMessage = gMsg;

            if (!Shell_NotifyIcon(NIM_ADD, &mNiData))
            {
                  DWORD dw = GetLastError();
                  TRACE_ERROR("Could not display ICON");
                  TRACE_SYS_CALL_CODE("Shell_NotifyIcon", dw);
            }
      }

      MSG msg;
      while (GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }
      gobjService.setStatus(SERVICE_STOPPED);
      TRACE_END();
}

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      int wmId, wmEvent;
      HMENU gMenu, gSubMenu;
      NOTIFYICONDATA            mNiData = {0};

      if (message == gMsg)
      {
            if (lParam == WM_RBUTTONUP)
            {
                  POINT pos = {0};
                  gMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_MENU_ICON));

                  if(gMenu)
                  {
                        gSubMenu = GetSubMenu(gMenu, 0);
                        GetCursorPos(&pos);

                        TrackPopupMenu(gSubMenu, TPM_RIGHTALIGN, pos.x, pos.y, 0, ghWnd, NULL);
            
                        DestroyMenu(gSubMenu);
                        DestroyMenu(gMenu);
                        
                  }
            }
      }
      else if (message == WM_COMMAND)
      {
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Analyse les sĂ©lections de menu :
            switch (wmId)
            {
            case ID_POPUP_2:
                  mNiData.cbSize = sizeof(NOTIFYICONDATA);
                  mNiData.uID = IDI_NOTIFY_ICON;
                  mNiData.hWnd = ghWnd;
                  Shell_NotifyIcon(NIM_DELETE, &mNiData);
                  DestroyWindow(ghWnd);
                  break;
            default:
                  return DefWindowProc(hWnd, message, wParam, lParam);
            }
      }
      else if (message == WM_DESTROY)
            PostQuitMessage(0);
      else
            return DefWindowProc(hWnd, message, wParam, lParam);

      return 0;
}

bool RegisterWindow()
{
      FUNC_USE_TRACE("RegisterWindow");
      TRACE_START();
      bool isSuccess = false;

      WNDCLASSEX wcx = {0};

      wcx.style                  = CS_HREDRAW | CS_VREDRAW;
   wcx.cbSize = sizeof(wcx);          // size of structure
   wcx.lpfnWndProc = MainWndProc;     // points to window procedure
   wcx.hInstance = GetModuleHandle(NULL);
   wcx.hIcon = NULL;
   wcx.hCursor = NULL;
   wcx.lpszClassName = "AlsMsgWndClass";  // name of window class

   isSuccess = RegisterClassEx(&wcx) != 0;

      if (!isSuccess)
        TRACE_SYS_CALL("RegisterClassEx");

      TRACE_END_RET(isSuccess, isSuccess);
      return isSuccess;
}

int main(int argc, char* argv[])
{
      FUNC_USE_TRACE("WinMain");
      NtService::startDispatcher(SERVICE_NAME, Run);
      return 0;
}
0
Ashron
Asked:
Ashron
1 Solution
 
Mikeh926Commented:
This is because in Vista, Services run in a different session to conventional applications, so they have no access to the desktop or any of it's components. Most, if not all conventional UI calls will fail.

Have a look at:
http://www.microsoft.com/whdc/system/vista/services.mspx

This contains a description of what's happening together with some possible workarounds.

Mike.
 

0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now