Объяснение логики GUID в Shell_NotifyIcon

#c #winapi

#c #winapi

Вопрос:

Пожалуйста, взгляните на следующий код. Если я сохраню GUID

{ 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x67 } }

затем уведомления поступают при запуске приложения и при отправке пользователем NIM_MODIFY во время выполнения.

Но, если я изменю GUID на

{ 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x66 } }

тогда значок отсутствует в трее. Журналы — это то, что ::Shell_NotifyIcon(NIM_DELETE, amp;m_notification_data) производит Unknown error , и ::Shell_NotifyIcon(NIM_ADD, amp;m_notification_data) Unknown error также производит. Я знаю, что этот идентификатор GUID (с 0x66 в конце) используется в другом приложении. в системе. Пожалуйста, объясните, как логика, связанная с GUID, работает при вызове Shell_NotifyIcon .

Код приведен ниже.

 ShellIcon notificMonWnd(NULL, LOG_PATH);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Разместите код здесь.

    // Инициализация глобальных строк
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    strcpy_s(szWindowClass, MYWNDCLASS);
    MyRegisterClass(hInstance);

    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, SW_HIDE))
    {
        return FALSE;
    }
    // ... more code
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Сохранить маркер экземпляра в глобальной переменной

   HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   // Initialize menu
   hPopupMenu = CreatePopupMenu();
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_ADD_TO_AUTORUN_CONTEXT_MENU_ITEM, "Add to Autorun");
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_REMOVE_FROM_AUTORUN_CONTEXT_MENU_ITEM, "Remove from Autorun");
   AppendMenuA(hPopupMenu, MF_SEPARATOR, 0, NULL);
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_OPEN_LOG_CONTEXT_MENU_ITEM, "Open log");
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_MODIFY_CONTEXT_MENU_ITEM, "Modify icon's data");
   AppendMenuA(hPopupMenu, MF_SEPARATOR, 0, NULL);
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_ABOUT_CONTEXT_MENU_ITEM, "About");
   AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_EXIT_CONTEXT_MENU_ITEM, "Exit");

   // Add icon to tray.
   notificMonWnd.notify(NIM_ADD, TRAY_ICON_MESSAGE, hWnd, IDI_EXCLAMATION);

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Разобрать выбор в меню:
            switch (wmId)
            {
            // ... more code
            case ID_TRAY_MODIFY_CONTEXT_MENU_ITEM:
                OnModifyIcon(hWnd);
                break;
            // ... more code                
            }
        }
        break;
        // ... more code
    }
}

void OnModifyIcon(HWND hwnd)
{
    Log::append(LOG_PATH, "OnModify", "entered");
    notificMonWnd.notify(NIM_MODIFY, TRAY_ICON_MESSAGE, hwnd, IDI_EXCLAMATION);
    Log::append(LOG_PATH, "OnModify", "exited");
}

 bool ShellIcon::notify(unsigned int dwMessage, UINT uCallbackMessage, HWND hwnd, LPSTR iconId)
{
    Log::append(m_log_path, "notify", "entered");

    ZeroMemory(amp;m_notification_data, sizeof(NOTIFYICONDATA));
    m_notification_data.cbSize = sizeof(NOTIFYICONDATA);

    BOOL r = ::Shell_NotifyIcon(NIM_DELETE, amp;m_notification_data); // delete old balloon message
    if (r == FALSE)
    {
        std::string msg;
        utils::getLastErrorMessage(msg);
        Log::append(m_log_path, "notify,NIM_DELETE", msg);
    }

    // N.B.!!! Displays balloon notification
    m_notification_data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_INFO;
    if (utils::isWin7OrLater())
    {
        m_notification_data.uFlags |= NIF_GUID;
        // N.B.!!! GUID differs from GUID used in earlier call to Shell_NotifyIcon in onCreate.
        // If you set the last value to 0x66 you'll never see the icon.
        m_notification_data.guidItem = { 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x67 } };
    }
    else
    {
        m_notification_data.uID = 1; // superfluous as guidItem was set
    }

    // Set szInfo field.
    m_notification_data.dwInfoFlags = NIIF_INFO; // info notification
    ::LoadString(m_module_instance, IDS_NOTIFICATION_TITLE, m_notification_data.szInfoTitle, sizeof(m_notification_data.szTip) / sizeof(TCHAR));
    ::LoadString(m_module_instance, IDS_DEFAULT_TIP_MESSAGE, m_notification_data.szInfo, sizeof(m_notification_data.szInfo) / sizeof(TCHAR));

    // Set szTip field.
    TCHAR notificationMessage[128] = { '' };
    // concatenate <title> - <tool tip message>
    ::LoadString(m_module_instance, IDS_NOTIFICATION_TITLE, m_notification_data.szTip, sizeof(m_notification_data.szTip) / sizeof(TCHAR));
    ::LoadString(m_module_instance, IDS_DEFAULT_TIP, notificationMessage, sizeof(notificationMessage) / sizeof(TCHAR));
    strcat_s(m_notification_data.szTip, _T(" - "));
    strcat_s(m_notification_data.szTip, notificationMessage);

    // Set icon.
    m_notification_data.hIcon = ::LoadIcon(m_module_instance, iconId);
    if (m_notification_data.hIcon == NULL)
    {
        std::string msg;
        utils::getLastErrorMessage(msg);
        Log::append(m_log_path, "notify,LoadIcon", msg);
    }

    // Please leave here code that may differ from original 
    // implementation of NotificationWindowMonitor::Notify
    m_notification_data.uVersion = NOTIFYICON_VERSION_4;
    m_notification_data.uCallbackMessage = uCallbackMessage;
    m_notification_data.hWnd = hwnd;

    r = ::Shell_NotifyIcon(dwMessage, amp;m_notification_data);
    if (r == FALSE)
    {
        std::string msg;
        utils::getLastErrorMessage(msg);
        Log::append(m_log_path, "notify,Shell_NotifyIcon", msg);
    }
    
    Log::append(m_log_path, "notify", "exited");

    return r;
}
 

Комментарии:

1. Вы получили ссылки на документацию, когда задавали тот же вопрос ранее. При удалении этого предыдущего вопроса вы также удалили всю информацию, которая была там представлена. Это бесполезно и довольно грубо.

2. @IInspectable, в документах говорится, что путь к двоичному файлу включен в регистрацию GUID значка и не может быть изменен. Как вы интерпретируете это предложение? Какую функцию мне вызвать, чтобы зарегистрировать GUID значка? Между ними я не перемещал двоичный файл.

3. В документации говорится о случайных попытках перерегистрировать GUID для значков области уведомлений. Распространенным режимом ошибки в этом случае было бы, если бы приложение, зарегистрировавшее GUID, было перемещено. В документации не описаны сценарии, при которых преднамеренная попытка перехватить GUID может завершиться неудачей. Злонамеренному игроку остается в качестве упражнения экстраполировать задокументированные сценарии ошибок.

4. @IInspectable, поэтому, когда я использовал этот идентификатор GUID с 0x66 в конце, это было интерпретировано как попытка перехватить этот идентификатор GUID моим приложением. Это то, что ты хочешь сказать?

5. Ну, а откуда у тебя этот GUID? Если вы справились с этим, скажем, guidgen.exe , тогда вы находитесь в лагере разработчиков, которым необходимо устранить проблему в результате несчастного случая, и документация применяется, как написано. Если вы получили GUID, проверив другой код и / или ресурсы, то вы находитесь в лагере разработчиков, которые пытаются бороться с системой. В этом случае вам придется перевести документацию в соответствии с ожиданиями злоумышленника. Основная аудитория документации — не злоумышленники.