- implemented EnumDirTree, SearchTreeForFile, SymFindFileInPath,
SymMatchFileName
- made use of SymFindFileInPath to lookup .dbg and .pdb files
- fixed a crash in CodeView enum handling
diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c
index 7f7c0f6..c8a1a65 100644
--- a/dlls/dbghelp/path.c
+++ b/dlls/dbghelp/path.c
@@ -28,6 +28,16 @@
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.@)
*
@@ -40,9 +50,7 @@
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
- const char* p = strrchr(FileName, '/');
- if (!p) p = FileName;
- if (!SearchPathA(SymbolPath, p, NULL, MAX_PATH, DebugFilePath, NULL))
+ 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);
@@ -92,15 +100,160 @@
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 RootPath, LPSTR InputPathName,
- LPSTR OutputPathBuffer)
+BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
{
- FIXME("(%s, %s, %s): stub\n",
- debugstr_a(RootPath), debugstr_a(InputPathName),
- debugstr_a(OutputPathBuffer));
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ 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;
}