Jump to content

voidtools' everything file search engine IPC


Recommended Posts

The nice ppl of voidtools created Everything Search Engine ( " Locate files and folders by name instantly. " ) :) 
And made a CLI program to search from the command line. They also gave the source code, and reading it, I see the IPC quite familiar.

// // // source for CLI.H
// Everything IPC test

// revision 2:
// fixed command line interpreting '-' as a switch inside text.

// revision 3:
// convert unicode to same code page as console.

// revision 4:
// removed write console because it has no support for piping.

// revision 5:
// added ChangeWindowMessageFilterEx (if available) for admin/user support.

// compiler options
#pragma warning(disable : 4311) // type cast void * to unsigned int
#pragma warning(disable : 4312) // type cast unsigned int to void *
#pragma warning(disable : 4244) // warning C4244: 'argument' : conversion from 'LONG_PTR' to 'LONG', possible loss of data
#pragma warning(disable : 4996) // deprecation

#include <windows.h>
#include <stdio.h>

#include "everything_ipc.h"

#define COPYDATA_IPCTEST_QUERYCOMPLETEW 0

#define MSGFLT_RESET        0
#define MSGFLT_ALLOW        1
#define MSGFLT_DISALLOW     2

typedef struct tagCHANGEFILTERSTRUCT {
  DWORD cbSize;
  DWORD ExtStatus;
} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;

static void write(wchar_t *text);
static void write_DWORD(DWORD value);
static int wstring_to_int(const wchar_t *s);

int sort = 0;
EVERYTHING_IPC_LIST *sort_list;
HMODULE user32_hdll = 0;

BOOL (WINAPI *pChangeWindowMessageFilterEx)(HWND hWnd,UINT message,DWORD action,PCHANGEFILTERSTRUCT pChangeFilterStruct) = 0;

int wstring_length(const wchar_t *s)
{
    const wchar_t *p;
    
    p = s;
    while(*p)
    {
        p++;
    }
    
    return (int)(p - s);
}

// query everything with search string
int sendquery(HWND hwnd,DWORD num,WCHAR *search_string,int regex,int match_case,int match_whole_word,int match_path)
{
    EVERYTHING_IPC_QUERY *query;
    int len;
    int size;
    HWND everything_hwnd;
    COPYDATASTRUCT cds;
    
    everything_hwnd = FindWindow(EVERYTHING_IPC_WNDCLASS,0);
    if (everything_hwnd)
    {
        len = wstring_length(search_string);
        
        size = sizeof(EVERYTHING_IPC_QUERY) - sizeof(WCHAR) + len*sizeof(WCHAR) + sizeof(WCHAR);
        
        query = (EVERYTHING_IPC_QUERY *)HeapAlloc(GetProcessHeap(),0,size);
        if (query)
        {
            query->max_results = num;
            query->offset = 0;
            query->reply_copydata_message = COPYDATA_IPCTEST_QUERYCOMPLETEW;
            query->search_flags = (regex?EVERYTHING_IPC_REGEX:0) | (match_case?EVERYTHING_IPC_MATCHCASE:0) | (match_whole_word?EVERYTHING_IPC_MATCHWHOLEWORD:0) | (match_path?EVERYTHING_IPC_MATCHPATH:0);
            query->reply_hwnd = hwnd;
            CopyMemory(query->search_string,search_string,(len+1)*sizeof(WCHAR));
        
            cds.cbData = size;
            cds.dwData = EVERYTHING_IPC_COPYDATAQUERY;
            cds.lpData = query;

            if (SendMessage(everything_hwnd,WM_COPYDATA,(WPARAM)hwnd,(LPARAM)&cds) == TRUE)
            {
                HeapFree(GetProcessHeap(),0,query);
                
                return 1;
            }
            else
            {
                write(L"Everything IPC service not running.\n");
            }

            HeapFree(GetProcessHeap(),0,query);
        }
        else
        {
            write(L"failed to allocate ");
            write_DWORD(size);
            write(L" bytes for IPC query.\n");
        }
    }
    else
    {
        // the everything window was not found.
        // we can optionally RegisterWindowMessage("EVERYTHING_IPC_CREATED") and 
        // wait for Everything to post this message to all top level windows when its up and running.
        write(L"Everything IPC window not found, IPC unavailable.\n");
    }

    return 0;
}

int compare_list_items(const void *a,const void *b)
{
    int i;
    
    i = wcsicmp(EVERYTHING_IPC_ITEMPATH(sort_list,a),EVERYTHING_IPC_ITEMPATH(sort_list,b));
    
    if (!i)
    {
        return wcsicmp(EVERYTHING_IPC_ITEMFILENAME(sort_list,a),EVERYTHING_IPC_ITEMFILENAME(sort_list,b));
    }
    else
    if (i > 0)
    {
        return 1;
    }
    else
    {
        return -1;
    }
}

static void write(wchar_t *text)
{
    DWORD mode;
    int wlen;
    DWORD numwritten;
    HANDLE output_handle;
    
    output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
    
    wlen = wstring_length(text);
    
    if (GetConsoleMode(output_handle,&mode))
    {
        WriteConsoleW(output_handle,text,wlen,&numwritten,0);
    }
    else
    {
        char *buf;
        int len;
        
        len = WideCharToMultiByte(GetConsoleCP(),0,text,wlen,0,0,0,0);
        if (len)
        {
            buf = HeapAlloc(GetProcessHeap(),0,len);
            if (buf)
            {
                WideCharToMultiByte(GetConsoleCP(),0,text,wlen,buf,len,0,0);
                
                WriteFile(output_handle,buf,len,&numwritten,0);
                
                HeapFree(GetProcessHeap(),0,buf);
            }
        }
    }
}

static void write_DWORD(DWORD value)
{
    wchar_t buf[256];
    wchar_t *d;
    
    d = buf + 256;
    *--d = 0;

    if (value)
    {
        DWORD i;
        
        i = value;
        
        while(i)
        {
            *--d = '0' + (i % 10);
            
            i /= 10;
        }
    }
    else
    {
        *--d = '0';
    }   
    
    write(d);
}

void listresultsW(EVERYTHING_IPC_LIST *list)
{
    DWORD i;
    
    if (sort)
    {
        sort_list = list;
        qsort(list->items,list->numitems,sizeof(EVERYTHING_IPC_ITEM),compare_list_items);
    }
        
    
    for(i=0;i<list->numitems;i++)
    {
        if (list->items[i].flags & EVERYTHING_IPC_DRIVE)
        {
            write(EVERYTHING_IPC_ITEMFILENAME(list,&list->items[i]));
            write(L"\r\n");
        }
        else
        {
            write(EVERYTHING_IPC_ITEMPATH(list,&list->items[i]));
            write(L"\\");
            write(EVERYTHING_IPC_ITEMFILENAME(list,&list->items[i]));
            write(L"\r\n");
        }
    }
    
    PostQuitMessage(0);
}

// custom window proc
LRESULT __stdcall window_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch(msg)
    {
        case WM_COPYDATA:
        {
            COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam;
            
            switch(cds->dwData)
            {
                case COPYDATA_IPCTEST_QUERYCOMPLETEW:
                    listresultsW((EVERYTHING_IPC_LIST *)cds->lpData);
                    return TRUE;
            }
            
            break;
        }
    }
    
    return DefWindowProc(hwnd,msg,wParam,lParam);
}

void help(void)
{
    write(L"-r Search the database using a basic POSIX regular expression.\n");
    write(L"-i Does a case sensitive search.\n");
    write(L"-w Does a whole word search.\n");
    write(L"-p Does a full path search.\n");
    write(L"-h --help Display this help.\n");
    write(L"-n <num> Limit the amount of results shown to <num>.\n");
    write(L"-s Sort by full path.\n");
}

// main entry
int main(int argc,char **argv)
{
    WNDCLASSEX wcex;
    HWND hwnd;
    MSG msg;
    int ret;
    int q;
    wchar_t *search;
    wchar_t *d;
    wchar_t *e;
    wchar_t *s;
    int match_whole_word = 0;
    int match_path = 0;
    int regex = 0;
    int match_case = 0;
    int wasexename = 0;
    int matchpath = 0;
    int i;
    int wargc;
    wchar_t **wargv;
    DWORD num = EVERYTHING_IPC_ALLRESULTS;
    
    ZeroMemory(&wcex,sizeof(wcex));
    wcex.cbSize = sizeof(wcex);
    
    if (!GetClassInfoEx(GetModuleHandle(0),TEXT("IPCTEST"),&wcex))
    {
        ZeroMemory(&wcex,sizeof(wcex));
        wcex.cbSize = sizeof(wcex);
        wcex.hInstance = GetModuleHandle(0);
        wcex.lpfnWndProc = window_proc;
        wcex.lpszClassName = TEXT("IPCTEST");
        
        if (!RegisterClassEx(&wcex))
        {
            write(L"failed to register IPCTEST window class\n");
            
            return 1;
        }
    }
    
    if (!(hwnd = CreateWindow(
        TEXT("IPCTEST"),
        TEXT(""),
        0,
        0,0,0,0,
        0,0,GetModuleHandle(0),0)))
    {
        write(L"failed to create IPCTEST window\n");
        
        return 1;
    }

    // allow the everything window to send a reply.
    user32_hdll = LoadLibrary(L"user32.dll");
    
    if (user32_hdll)
    {
        pChangeWindowMessageFilterEx = (BOOL (WINAPI *)(HWND hWnd,UINT message,DWORD action,PCHANGEFILTERSTRUCT pChangeFilterStruct))GetProcAddress(user32_hdll,"ChangeWindowMessageFilterEx");

        if (pChangeWindowMessageFilterEx)
        {
            pChangeWindowMessageFilterEx(hwnd,WM_COPYDATA,MSGFLT_ALLOW,0);
        }
    }
    
    wargv = CommandLineToArgvW(GetCommandLineW(),&wargc);

    search = HeapAlloc(GetProcessHeap(),0,65536);
    if (!search)
    {
        write(L"failed to allocate ");
        write_DWORD(65536);
        write(L" bytes for search buffer.\n");
        
        if (user32_hdll)
        {
            FreeLibrary(user32_hdll);
        }

        return 1;
    }
    
    d = search;

    // allow room for null terminator
    e = search + (65536 / sizeof(wchar_t)) - 1;
    
    wargc--;
    i = 0;
    for(;;)
    {
        if (i >= wargc) break;
        
        if (wcsicmp(wargv[i+1],L"-r") == 0)
        {
            regex = 1;
        }
        else
        if (wcsicmp(wargv[i+1],L"-i") == 0)
        {
            match_case = 1;
        }
        else
        if (wcsicmp(wargv[i+1],L"-w") == 0)
        {
            match_whole_word = 1;
        }
        else
        if (wcsicmp(wargv[i+1],L"-p") == 0)
        {
            match_path = 1;
        }
        else
        if (wcsicmp(wargv[i+1],L"-s") == 0)
        {
            sort = 1;
        }
        else
        if ((wcsicmp(wargv[i+1],L"-n") == 0) && (i + 1 < wargc))
        {
            i++;
            
            num = wstring_to_int(wargv[i+1]);
        }
        else
        if (wargv[i+1][0] == '-')
        {
            // unknwon command
            help();
            HeapFree(GetProcessHeap(),0,search);
        
            if (user32_hdll)
            {
                FreeLibrary(user32_hdll);
            }

            return 1;
        }
        else
        {
            // keep quotes ?
            q = 0;
            
            s = wargv[i+1];
            while(*s)
            {
                if ((*s == ' ') || (*s == '\t') || (*s == '\r') || (*s == '\n'))
                {
                    q = 1;
                    break
                }
                
                s++;
            }
            
            if ((d != search) && (d < e)) *d++ = ' ';

            if (q)
            {
                if (d < e) *d++ = '"';
            }

            // copy append to search
            s = wargv[i+1];
            while(*s)
            {
                if (d < e) *d++ = *s;
                s++;
            }

            if (q)
            {
                if (d < e) *d++ = '"';
            }
        }
        
        i++;
    }
    
    // null terminate
    *d = 0;

    if (!sendquery(hwnd,num,search,regex,match_case,match_whole_word,match_path)) 
    {
        // send query reports error
        
        HeapFree(GetProcessHeap(),0,search);
        
        if (user32_hdll)
        {
            FreeLibrary(user32_hdll);
        }

        return 1;
    }

    HeapFree(GetProcessHeap(),0,search);

    // message pump
loop:

    // update windows
    if (PeekMessage(&msg,NULL,0,0,0)) 
    {
        ret = (int)GetMessage(&msg,0,0,0);
        if (ret <= 0) goto exit;

        // let windows handle it.
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }           
    else
    {
        WaitMessage();
    }
    
    goto loop;

exit:
    
    if (user32_hdll)
    {
        FreeLibrary(user32_hdll);
    }
        
    return 0;
}

static int wstring_to_int(const wchar_t *s)
{
    const wchar_t *p;
    int value;
    
    p = s;
    value = 0;
    
    while(*p)
    {
        if (!((*p >= '0') && (*p <= '9')))
        {
            break;
        }
        
        value *= 10;
        value += *p - '0';
        p++;
    }
    
    return value;
}
// // // source for everything_ipc.h

// Everything IPC

#ifndef _EVERYTHING_IPC_H_
#define _EVERYTHING_IPC_H_

// C
#ifdef __cplusplus
extern "C" {
#endif

// 1 byte packing for our varible sized structs
#pragma pack(push, 1)

// WM_USER (send to the taskbar notification window)
// SendMessage(FindWindow(EVERYTHING_IPC_WNDCLASS,0),WM_USER,EVERYTHING_IPC_*,lParam)
// version format: major.minor.revision.build 
// example: 1.1.4.309
#define EVERYTHING_IPC_GET_MAJOR_VERSION        0 // int major_version = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_MAJOR_VERSION,0);
#define EVERYTHING_IPC_GET_MINOR_VERSION        1 // int minor_version = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_MINOR_VERSION,0);
#define EVERYTHING_IPC_GET_REVISION             2 // int revision = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_REVISION,0);
#define EVERYTHING_IPC_GET_BUILD_NUMBER         3 // int build = (int)SendMessage(hwnd,WM_USER,EVERYTHING_IPC_GET_BUILD,0);

// find the everything window
#define EVERYTHING_IPC_WNDCLASS         TEXT("EVERYTHING_TASKBAR_NOTIFICATION")

// find a everything search window
#define EVERYTHING_IPC_SEARCH_WNDCLASS  TEXT("EVERYTHING")

// this global window message is sent to all top level windows when everything starts.
#define EVERYTHING_IPC_CREATED          TEXT("EVERYTHING_IPC_CREATED")

// search flags for querys
#define EVERYTHING_IPC_MATCHCASE        0x00000001  // match case
#define EVERYTHING_IPC_MATCHWHOLEWORD   0x00000002  // match whole word
#define EVERYTHING_IPC_MATCHPATH        0x00000004  // include paths in search
#define EVERYTHING_IPC_REGEX            0x00000008  // enable regex

// item flags
#define EVERYTHING_IPC_FOLDER           0x00000001  // The item is a folder. (its a file if not set)
#define EVERYTHING_IPC_DRIVE            0x00000002  // The folder is a drive. Path will be an empty string. 
                                                    // (will also have the folder bit set)

// the WM_COPYDATA message for a query.
#define EVERYTHING_IPC_COPYDATAQUERYA   1
#define EVERYTHING_IPC_COPYDATAQUERYW   2

// all results
#define EVERYTHING_IPC_ALLRESULTS       0xFFFFFFFF // all results

// macro to get the filename of an item
#define EVERYTHING_IPC_ITEMFILENAMEA(list,item) (CHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMA *)(item))->filename_offset)
#define EVERYTHING_IPC_ITEMFILENAMEW(list,item) (WCHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->filename_offset)

// macro to get the path of an item
#define EVERYTHING_IPC_ITEMPATHA(list,item) (CHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->path_offset)
#define EVERYTHING_IPC_ITEMPATHW(list,item) (WCHAR *)((CHAR *)(list) + ((EVERYTHING_IPC_ITEMW *)(item))->path_offset)

//
// Varible sized query struct sent to everything.
//
// sent in the form of a WM_COPYDAYA message with EVERYTHING_IPC_COPYDATAQUERY as the 
// dwData member in the COPYDATASTRUCT struct.
// set the lpData member of the COPYDATASTRUCT struct to point to your EVERYTHING_IPC_QUERY struct.
// set the cbData member of the COPYDATASTRUCT struct to the size of the 
// EVERYTHING_IPC_QUERY struct minus the size of a CHAR plus the length of the search string in bytes plus 
// one CHAR for the null terminator.
//
// NOTE: to determine the size of this structure use 
// ASCII: sizeof(EVERYTHING_IPC_QUERYA) - sizeof(CHAR) + strlen(search_string)*sizeof(CHAR) + sizeof(CHAR)
// UNICODE: sizeof(EVERYTHING_IPC_QUERYW) - sizeof(WCHAR) + wcslen(search_string)*sizeof(WCHAR) + sizeof(WCHAR)
//
// NOTE: Everything will only do one query per window.
// Sending another query when a query has not completed 
// will cancel the old query and start the new one. 
//
// Everything will send the results to the reply_hwnd in the form of a 
// WM_COPYDAYA message with the dwData value you specify.
// 
// Everything will return TRUE if successful.
// returns FALSE if not supported.
//
// If you query with EVERYTHING_IPC_COPYDATAQUERYW, the results sent from Everything will be Unicode.
//

typedef struct EVERYTHING_IPC_QUERYW
{
    // the window that will receive the new results.
    HWND reply_hwnd;
    
    // the value to set the dwData member in the COPYDATASTRUCT struct 
    // sent by Everything when the query is complete.
    ULONG_PTR reply_copydata_message;
    
    // search flags (see EVERYTHING_MATCHCASE | EVERYTHING_MATCHWHOLEWORD | EVERYTHING_MATCHPATH)
    DWORD search_flags; 
    
    // only return results after 'offset' results (0 to return the first result)
    // useful for scrollable lists
    DWORD offset; 
    
    // the number of results to return 
    // zero to return no results
    // EVERYTHING_IPC_ALLRESULTS to return ALL results
    DWORD max_results;

    // null terminated string. arbitrary sized search_string buffer.
    WCHAR search_string[1];
    
}EVERYTHING_IPC_QUERYW;

// ASCII version
typedef struct EVERYTHING_IPC_QUERYA
{
    // the window that will receive the new results.
    HWND reply_hwnd;
    
    // the value to set the dwData member in the COPYDATASTRUCT struct 
    // sent by Everything when the query is complete.
    ULONG_PTR reply_copydata_message;
    
    // search flags (see EVERYTHING_MATCHCASE | EVERYTHING_MATCHWHOLEWORD | EVERYTHING_MATCHPATH)
    DWORD search_flags; 
    
    // only return results after 'offset' results (0 to return the first result)
    // useful for scrollable lists
    DWORD offset; 
    
    // the number of results to return 
    // zero to return no results
    // EVERYTHING_IPC_ALLRESULTS to return ALL results
    DWORD max_results;

    // null terminated string. arbitrary sized search_string buffer.
    CHAR search_string[1];
    
}EVERYTHING_IPC_QUERYA;

//
// Varible sized result list struct received from Everything.
//
// Sent in the form of a WM_COPYDATA message to the hwnd specifed in the 
// EVERYTHING_IPC_QUERY struct.
// the dwData member of the COPYDATASTRUCT struct will match the sent
// reply_copydata_message member in the EVERYTHING_IPC_QUERY struct.
// 
// make a copy of the data before returning.
//
// return TRUE if you processed the WM_COPYDATA message.
//

typedef struct EVERYTHING_IPC_ITEMW
{
    // item flags
    DWORD flags;

    // The offset of the filename from the beginning of the list structure.
    // (wchar_t *)((char *)everything_list + everythinglist->name_offset)
    DWORD filename_offset;

    // The offset of the filename from the beginning of the list structure.
    // (wchar_t *)((char *)everything_list + everythinglist->path_offset)
    DWORD path_offset;
    
}EVERYTHING_IPC_ITEMW;

typedef struct EVERYTHING_IPC_ITEMA
{
    // item flags
    DWORD flags;

    // The offset of the filename from the beginning of the list structure.
    // (char *)((char *)everything_list + everythinglist->name_offset)
    DWORD filename_offset;

    // The offset of the filename from the beginning of the list structure.
    // (char *)((char *)everything_list + everythinglist->path_offset)
    DWORD path_offset;
    
}EVERYTHING_IPC_ITEMA;

typedef struct EVERYTHING_IPC_LISTW
{
    // the total number of folders found.
    DWORD totfolders;
    
    // the total number of files found.
    DWORD totfiles;
    
    // totfolders + totfiles
    DWORD totitems;
    
    // the number of folders available.
    DWORD numfolders;
    
    // the number of files available.
    DWORD numfiles;
    
    // the number of items available.
    DWORD numitems;

    // index offset of the first result in the item list.
    DWORD offset;
    
    // arbitrary sized item list. 
    // use numitems to determine the actual number of items available.
    EVERYTHING_IPC_ITEMW items[1];
    
}EVERYTHING_IPC_LISTW;

typedef struct EVERYTHING_IPC_LISTA
{
    // the total number of folders found.
    DWORD totfolders;
    
    // the total number of files found.
    DWORD totfiles;
    
    // totfolders + totfiles
    DWORD totitems;
    
    // the number of folders available.
    DWORD numfolders;
    
    // the number of files available.
    DWORD numfiles;
    
    // the number of items available.
    DWORD numitems;

    // index offset of the first result in the item list.
    DWORD offset;
    
    // arbitrary sized item list. 
    // use numitems to determine the actual number of items available.
    EVERYTHING_IPC_ITEMA items[1];
    
}EVERYTHING_IPC_LISTA;

#ifdef UNICODE
#define EVERYTHING_IPC_COPYDATAQUERY    EVERYTHING_IPC_COPYDATAQUERYW
#define EVERYTHING_IPC_ITEMFILENAME     EVERYTHING_IPC_ITEMFILENAMEW
#define EVERYTHING_IPC_ITEMPATH         EVERYTHING_IPC_ITEMPATHW
#define EVERYTHING_IPC_QUERY            EVERYTHING_IPC_QUERYW
#define EVERYTHING_IPC_ITEM             EVERYTHING_IPC_ITEMW
#define EVERYTHING_IPC_LIST             EVERYTHING_IPC_LISTW
#else
#define EVERYTHING_IPC_COPYDATAQUERY    EVERYTHING_IPC_COPYDATAQUERYA
#define EVERYTHING_IPC_ITEMFILENAME     EVERYTHING_IPC_ITEMFILENAMEA
#define EVERYTHING_IPC_ITEMPATH         EVERYTHING_IPC_ITEMPATHA
#define EVERYTHING_IPC_QUERY            EVERYTHING_IPC_QUERYA
#define EVERYTHING_IPC_ITEM             EVERYTHING_IPC_ITEMA
#define EVERYTHING_IPC_LIST             EVERYTHING_IPC_LISTA
#endif


// restore packing
#pragma pack(pop)

// end extern C
#ifdef __cplusplus
}
#endif

#endif // _EVERYTHING_H_

so, the reason for this posting is: it can be implemented in AutoIt3 B)

I personally can run es.exe and get the results from the command line, that is I, with my knowing, now, some of you can make a beautiful UDF ( and I say some of you, because, I would not know where to start :( )

I use everything for everything, very handy tool. If you ever get to see it work, you'll see how handy it is, mostly if you have many terabytes of files ( or just plain can't remember where a file is at )

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...