blob: c8a1a6504cab64f35dd128b3666fab29f3f21af7 [file] [log] [blame]
/*
* File path.c - managing path in debugging environments
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dbghelp_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
static inline char* file_name(char* str)
{
char* p;
for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
return p + 1;
}
/******************************************************************
* FindDebugInfoFile (DBGHELP.@)
*
*/
HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePath)
{
HANDLE h;
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
return NULL;
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
}
/******************************************************************
* FindDebugInfoFileEx (DBGHELP.@)
*
*/
HANDLE WINAPI FindDebugInfoFileEx(PSTR FileName, PSTR SymbolPath,
PSTR DebugFilePath,
PFIND_DEBUG_FILE_CALLBACK Callback,
PVOID CallerData)
{
FIXME("(%s %s %p %p %p): stub\n",
FileName, SymbolPath, DebugFilePath, Callback, CallerData);
return NULL;
}
/******************************************************************
* FindExecutableImage (DBGHELP.@)
*
*/
HANDLE WINAPI FindExecutableImage(PSTR FileName, PSTR SymbolPath, PSTR ImageFilePath)
{
HANDLE h;
if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
return NULL;
h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
}
/***********************************************************************
* MakeSureDirectoryPathExists (DBGHELP.@)
*/
BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
{
if (CreateDirectoryA(DirPath, NULL)) return TRUE;
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
SetLastError(ERROR_SUCCESS);
return TRUE;
}
return FALSE;
}
/******************************************************************
* SymMatchFileName (DBGHELP.@)
*
*/
BOOL WINAPI SymMatchFileName(char* file, char* match,
char** filestop, char** matchstop)
{
char* fptr;
char* mptr;
TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
fptr = file + strlen(file) - 1;
mptr = match + strlen(match) - 1;
while (fptr >= file && mptr >= match)
{
if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
break;
fptr--; mptr--;
}
if (filestop) *filestop = fptr;
if (matchstop) *matchstop = mptr;
return mptr == match - 1;
}
static BOOL do_search(const char* file, char* buffer,
PENUMDIRTREE_CALLBACK cb, void* user)
{
HANDLE h;
WIN32_FIND_DATAA fd;
unsigned pos;
BOOL found = FALSE;
pos = strlen(buffer);
if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
strcpy(buffer + pos, "*.*");
if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
return FALSE;
/* doc doesn't specify how the tree is enumerated...
* doing a depth first based on, but may be wrong
*/
do
{
if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
strcpy(buffer + pos, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
found = do_search(file, buffer, cb, user);
else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
{
if (!cb || cb(buffer, user)) found = TRUE;
}
} while (!found && FindNextFileA(h, &fd));
if (!found) buffer[--pos] = '\0';
FindClose(h);
return found;
}
/***********************************************************************
* SearchTreeForFile (DBGHELP.@)
*/
BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
{
TRACE("(%s, %s, %p)\n",
debugstr_a(root), debugstr_a(file), buffer);
strcpy(buffer, root);
return do_search(file, buffer, NULL, NULL);
}
/******************************************************************
* EnumDirTree (DBGHELP.@)
*
*
*/
BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
LPSTR buffer, PENUMDIRTREE_CALLBACK cb, void* user)
{
TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
strcpy(buffer, root);
return do_search(file, buffer, cb, user);
}
struct sffip
{
PVOID id;
DWORD two;
DWORD three;
DWORD flags;
PFINDFILEINPATHCALLBACK cb;
void* user;
};
static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
{
struct sffip* s = (struct sffip*)user;
/* FIXME: should check that id/two/three match the file pointed
* by buffer
*/
/* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
* convention to stop/continue enumeration. sigh.
*/
return !(s->cb)((char*)buffer, s->user);
}
/******************************************************************
* SymFindFileInPath (DBGHELP.@)
*
*/
BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
PVOID id, DWORD two, DWORD three, DWORD flags,
LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
PVOID user)
{
struct sffip s;
struct process* pcs = process_find_by_handle(hProcess);
char tmp[MAX_PATH];
char* ptr;
TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
hProcess, searchPath, file, id, two, three, flags,
buffer, cb, user);
if (!pcs) return FALSE;
if (!searchPath) searchPath = pcs->search_path;
s.id = id;
s.two = two;
s.three = three;
s.flags = flags;
s.cb = cb;
s.user = user;
file = file_name(file);
while (searchPath)
{
ptr = strchr(searchPath, ';');
if (ptr)
{
memcpy(tmp, searchPath, ptr - searchPath);
tmp[ptr - searchPath] = 0;
searchPath = ptr + 1;
}
else
{
strcpy(tmp, searchPath);
searchPath = NULL;
}
if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
}
return FALSE;
}