-- search for a .DLL that contains a given routine
-- usage:  
--      exw dsearch [routine] 
--
-- If you don't supply a string on the command line you will be prompted 
-- for it. 


-- Some of the common WIN32 .DLLs. Feel free to add more.
sequence dll_list
dll_list = {
    "kernel32.dll",
    "user32.dll",
    "gdi32.dll",
    "winmm.dll",
    "comdlg32.dll",
    "comctl32.dll"
}

include file.e
include dll.e
include machine.e

constant KEYB = 0, SCREEN = 1

constant TRUE = 1, FALSE = 0

type boolean(integer x)
    return x = 0 or x = 1
end type

type c_routine(integer x)
    return x >= -1 and x <= 1000
end type

sequence cmd, orig_string

integer scanned, no_open
scanned = 0
no_open = 0

c_routine FreeLibrary, GetProcAddress

atom string_pointer
sequence routine_name

function scan(sequence file_name)
-- process an eligible file
    boolean found_in_file
    atom lib
    integer code
    
    lib = open_dll(file_name)
    if lib = 0 then
	no_open += 1
	puts(SCREEN, file_name & ": Couldn't open.\n")
	return 0
    end if
    printf(SCREEN, "%s: ", {file_name})
    scanned += 1
    string_pointer = allocate(length(routine_name)+1)
    poke(string_pointer, routine_name & 0)
    found_in_file = FALSE
    if c_func(GetProcAddress, {lib, string_pointer}) then
	printf(SCREEN, "\n\n%s was FOUND in %s\n", {routine_name, file_name})
	found_in_file = TRUE
    end if
    free(string_pointer)
    code = c_func(FreeLibrary, {lib})
    if not code then
	printf(SCREEN, "\nFreeLibrary failed - code: %d\n", code)
    end if
    return found_in_file
end function

procedure CSetup()
-- set up C routines that we need:
    atom kernel32
    
    kernel32 = open_dll("kernel32.dll")
    if kernel32 = 0 then
	puts(SCREEN, "Can't open kernel32.dll!\n")
	abort(1)
    end if
    FreeLibrary = define_c_func(kernel32, "FreeLibrary", {C_POINTER}, C_INT)
    if FreeLibrary = -1 then
	puts(1, "Can't find FreeLibrary\n")
	abort(1)
    end if
    GetProcAddress = define_c_func(kernel32, "GetProcAddress", 
		     {C_POINTER, C_POINTER}, C_INT)
    if GetProcAddress = -1 then
	puts(1, "Can't find GetProcAddress\n")
	abort(1)
    end if
end procedure

function delete_trailing_white(sequence name)
-- get rid of blanks, tabs, newlines at end of string
    while length(name) > 0 do
	if find(name[length(name)], "\n\r\t ") then
	    name = name[1..length(name)-1]
	else
	    exit
	end if
    end while
    return name
end function

CSetup()

cmd = command_line()   -- exw dsearch [string]

if length(cmd) >= 3 then
    orig_string = cmd[3]
else
    puts(SCREEN, "C function name:")
    orig_string = delete_trailing_white(gets(KEYB))
    puts(SCREEN, '\n')
end if

routine_name = orig_string

procedure locate(sequence name)
    routine_name = name
    puts(1, "Looking for " & routine_name & "\n ")
    for i = 1 to length(dll_list) do
	if scan(dll_list[i]) then
	    if getc(0) then
	    end if
	    abort(1)
	end if
    end for
    puts(1, '\n')
end procedure

if length(routine_name) = 0 then
    abort(0)
end if

locate(orig_string)
locate(orig_string & "A")
locate(orig_string & "Ex")
locate(orig_string & "ExA")

puts(1, "\nCouldn't find " & orig_string & '\n')
puts(1, "Press Enter\n")

if getc(0) then
end if

