2 * File path.c - managing path in debugging environments
4 * Copyright (C) 2004, Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "dbghelp_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
31 static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
33 static inline char* file_name(char* str)
37 for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
41 /******************************************************************
42 * FindDebugInfoFile (DBGHELP.@)
45 HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePath)
49 h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
50 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
51 if (h == INVALID_HANDLE_VALUE)
53 if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
55 h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
56 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
58 return (h == INVALID_HANDLE_VALUE) ? NULL : h;
61 /******************************************************************
62 * FindDebugInfoFileEx (DBGHELP.@)
65 HANDLE WINAPI FindDebugInfoFileEx(PSTR FileName, PSTR SymbolPath,
67 PFIND_DEBUG_FILE_CALLBACK Callback,
70 FIXME("(%s %s %p %p %p): stub\n",
71 FileName, SymbolPath, DebugFilePath, Callback, CallerData);
75 /******************************************************************
76 * FindExecutableImage (DBGHELP.@)
79 HANDLE WINAPI FindExecutableImage(PSTR FileName, PSTR SymbolPath, PSTR ImageFilePath)
82 if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
84 h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
85 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
86 return (h == INVALID_HANDLE_VALUE) ? NULL : h;
89 /***********************************************************************
90 * MakeSureDirectoryPathExists (DBGHELP.@)
92 BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
94 if (CreateDirectoryA(DirPath, NULL)) return TRUE;
95 if (GetLastError() == ERROR_ALREADY_EXISTS)
97 SetLastError(ERROR_SUCCESS);
103 /******************************************************************
104 * SymMatchFileName (DBGHELP.@)
107 BOOL WINAPI SymMatchFileName(char* file, char* match,
108 char** filestop, char** matchstop)
113 TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
115 fptr = file + strlen(file) - 1;
116 mptr = match + strlen(match) - 1;
118 while (fptr >= file && mptr >= match)
120 if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
124 if (filestop) *filestop = fptr;
125 if (matchstop) *matchstop = mptr;
127 return mptr == match - 1;
130 static BOOL do_search(const char* file, char* buffer,
131 PENUMDIRTREE_CALLBACK cb, void* user)
138 pos = strlen(buffer);
139 if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
140 strcpy(buffer + pos, "*.*");
141 if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
143 /* doc doesn't specify how the tree is enumerated...
144 * doing a depth first based on, but may be wrong
148 if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
150 strcpy(buffer + pos, fd.cFileName);
151 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
152 found = do_search(file, buffer, cb, user);
153 else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
155 if (!cb || cb(buffer, user)) found = TRUE;
157 } while (!found && FindNextFileA(h, &fd));
158 if (!found) buffer[--pos] = '\0';
164 /***********************************************************************
165 * SearchTreeForFile (DBGHELP.@)
167 BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
169 TRACE("(%s, %s, %p)\n",
170 debugstr_a(root), debugstr_a(file), buffer);
171 strcpy(buffer, root);
172 return do_search(file, buffer, NULL, NULL);
175 /******************************************************************
176 * EnumDirTree (DBGHELP.@)
180 BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
181 LPSTR buffer, PENUMDIRTREE_CALLBACK cb, void* user)
183 TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
185 strcpy(buffer, root);
186 return do_search(file, buffer, cb, user);
195 PFINDFILEINPATHCALLBACK cb;
199 static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
201 struct sffip* s = (struct sffip*)user;
203 /* FIXME: should check that id/two/three match the file pointed
206 /* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
207 * convention to stop/continue enumeration. sigh.
209 return !(s->cb)((char*)buffer, s->user);
212 /******************************************************************
213 * SymFindFileInPath (DBGHELP.@)
216 BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
217 PVOID id, DWORD two, DWORD three, DWORD flags,
218 LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
222 struct process* pcs = process_find_by_handle(hProcess);
226 TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
227 hProcess, searchPath, file, id, two, three, flags,
230 if (!pcs) return FALSE;
231 if (!searchPath) searchPath = pcs->search_path;
240 file = file_name(file);
244 ptr = strchr(searchPath, ';');
247 memcpy(tmp, searchPath, ptr - searchPath);
248 tmp[ptr - searchPath] = 0;
249 searchPath = ptr + 1;
253 strcpy(tmp, searchPath);
256 if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;