How to find paltalk commands at runtime.

Here you can talk about C++ And C# And Other languages programming.

How to find paltalk commands at runtime.

Postby Chike » Thu Dec 06, 2007 6:28 pm


As a follow-up to problem locking the mic using code here is a code example of one way it can be done:
Code: Select all
#include <windows.h>
#include <stdio.h>
#include <ctype.h>

struct command {
   const char *text;   // in: text to look for
   int code;         // out: command number
};

command my_commands[] = {
   { "lock mic", 0},
   { "push to talk", 0},
   { "console", 0},
   { "send a file", 0},
   { "all hands", 0},
   { "view webcam", 0},
   { "red dot", 0},
   { NULL, 0} // stop when null
};

struct fill_cmd_param {
   command *commands;
   int nfound;
};

static void fill_commands(HMENU hMenu, fill_cmd_param *fcpp);

int main(int argc, TCHAR* argv[])
{
   HWND hwnd = FindWindow("DlgGroupChat Window Class", NULL);
   
   if (hwnd == NULL)
      return 1;
   
   HMENU hmenu = GetMenu(hwnd);

   if (hmenu == NULL)
      return 2;

   fill_cmd_param fcp = {my_commands, 0};

   fill_commands(hmenu, &fcp);
   if (fcp.nfound > 0) {
      printf("found %d commands:\n", fcp.nfound);
      for (command *cmd = my_commands; cmd->text != NULL; ++cmd) {
         if (cmd->code != 0) {
            printf("  %s:\t%d\n", cmd->text, cmd->code);
         } else {
            printf("  %s:\t(not found)\n", cmd->text);
         }
      }
   }
   return 0;
}

// find substring sub in string str, case-insensitive
static
const char *strstri(const char *str, const char *sub)
{
   size_t str_len = strlen(str);
   size_t sub_len = strlen(sub);

   if (sub_len > str_len)
      return NULL;

   const char *end = str + str_len - sub_len + 1;

   for (const char *s = str; s != end; ++s) {
      if (toupper(*s) == toupper(*sub) ) {
         const char *ssub = &sub[1];
         for (const char *ss = &s[1];
               *ssub && (toupper(*ss) == toupper(*ssub)); ++ss)
            ++ssub;
         if (*ssub == '\0')
            return s;
      }
   }
   return NULL;
}

// walk through all menu items/sub menues and fill the
static
void fill_commands(HMENU hmenu, fill_cmd_param *fcpp)
{
   if (hmenu == NULL)
      return;

   int nitems = GetMenuItemCount(hmenu);

   for (int i = 0; i < nitems; ++i) {
      UINT mstate = GetMenuState(hmenu, i, MF_BYPOSITION);

      if (mstate & MF_POPUP) {
         // search sub menu - recursive
         fill_commands(GetSubMenu(hmenu, i), fcpp);
      } else if (! (mstate & (MF_BITMAP | MF_OWNERDRAW))){ // imply MF_STRING
         char str[64];
         if (GetMenuString(hmenu, i, str, sizeof(str), MF_BYPOSITION) > 0) {
            // match with one of our comma
            for (command *cmd = fcpp->commands; cmd->text != NULL; ++cmd) {
               if (strstri(str, cmd->text) != NULL) { // match
                  // get menu cmd
                  int code =  GetMenuItemID(hmenu, i);
                  if (cmd->code != 0) { // duplicate - which one to choose?
                     fprintf(stderr, "%s: %d -> %d\n", cmd->text, cmd->code, code);
                  } else {
                     cmd->code = code;
                     ++fcpp->nfound;
                  }
                  break;
               }
            }
         }
      }
   }

}


output:
found 6 commands:
lock mic: 33340
push to talk: 33343
console: 32998
send a file: 33231
all hands: 32995
view webcam: 33163
red dot: (not found)
Image
Chike
imFiles Master
imFiles Master
 
Posts: 581
Joined: Sun May 13, 2007 6:20 pm

Re: How to find paltalk commands at runtime.

Postby Chike » Sat Dec 08, 2007 5:53 am

One problem with that code is that the room menues do not have all the commands you may want to look for.
So here's a nother way to do it by reading the menu resources.
I excluded the some of the functions you can find in the 1st post.
Code: Select all
struct command {
   const char *text;
   int code;
};

command my_commands[] = {
   { "lock mic", 0},
   { "push to talk", 0},
   { "console", 0},
   { "send a file", 0},
   { "all hands", 0},
   { "view webcam", 0},
   { "red dot", 0},
   { "bounce", 0},
   { NULL, 0} // stop when null
};

static int find_commands(const char *fname, command *commands);

int main(int argc, TCHAR* argv[])
{
   HWND hwnd = FindWindow("SEINFELD_SUPERMAN", NULL);

   if (hwnd == NULL)
      return 1;

   DWORD dwprocessid;
   // get process id - needed for OpenProcess
   if (GetWindowThreadProcessId(hwnd, &dwprocessid) == 0)
      return 2;

   HANDLE hprocess = OpenProcess(
      // access needed to enum and read resources
      PROCESS_QUERY_INFORMATION |   PROCESS_VM_READ,
      // don't care about handle inharitence
      FALSE,
      dwprocessid);

   if (hprocess == NULL)
      return 3;

   char fname[MAX_PATH];
   // get paltalk process exectutable path
   int fnamelen = GetModuleFileNameEx(hprocess, NULL, fname, sizeof(fname));

   if (fnamelen > 0) {
      int n = find_commands(fname, my_commands);
      if (n > 0) {
         printf("found %d commands:\n", n);
         for (command *cmd = my_commands; cmd->text != NULL; ++cmd) {
            if (cmd->code != 0) {
               printf("\t%s:\t%d\n", cmd->text, cmd->code);
            } else {
               printf("\t%s:\t(not found)\n", cmd->text);
            }
         }
      }
   }
   CloseHandle(hprocess);
   return (fnamelen > 0) ? 0 : 4;
}

// doing it the easy way - too lazy to parse menu resource structure
// loads each menu resource and send it to fill_commands
static
BOOL CALLBACK MyEnumResProc(
   HMODULE hmodule,
   LPCTSTR lpsztype,
   LPTSTR lpszname,
   LONG_PTR lparam)
{
   if (lpsztype == RT_MENU) { // sanity
      HMENU hmenu = LoadMenu(hmodule, lpszname);

      if (hmenu != NULL) {
         fill_commands(hmenu, ((fill_cmd_param*)lparam));
         DestroyMenu(hmenu);
      }
   }
   return TRUE;
}

static
int find_commands(const char *fname, command *commands)
{
   // load library as resource library without calling startup code
   HMODULE hmodule = LoadLibraryEx(fname, NULL, LOAD_LIBRARY_AS_DATAFILE);

   if (hmodule != NULL) {
      fill_cmd_param fcp = {commands, 0};
      // enumerate menu resources
      EnumResourceNames(hmodule, RT_MENU, MyEnumResProc, LONG_PTR(&fcp));
      FreeLibrary(hmodule);
      return fcp.nfound;
   }
   return 0;
}


output:
view webcam: 33163 -> 32905
send a file: 33231 -> 32902
push to talk: 33343 -> 33343
send a file: 33231 -> 33109
push to talk: 33343 -> 33338
lock mic: 33340 -> 33339
view webcam: 33163 -> 32905
send a file: 33231 -> 32902
view webcam: 33163 -> 32905
bounce: 32947 -> 32947
red dot: 32946 -> 32946
view webcam: 33163 -> 32905
send a file: 33231 -> 32902
found 8 commands:
lock mic: 33340
push to talk: 33343
console: 32998
send a file: 33231
all hands: 32995
view webcam: 33163
red dot: 32946
bounce: 32947

There are some duplicates, part are the same codes, others differ.
I haven't tested to see if all duplicates work or which does or doesn't.
Image
Chike
imFiles Master
imFiles Master
 
Posts: 581
Joined: Sun May 13, 2007 6:20 pm


Return to C++, C# And Others Programming

 


  • Related topics
    Replies
    Views
    Last post

Who is online

Users browsing this forum: No registered users and 0 guests