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
)
95 const char *p
= DirPath
;
98 if (p
[0] && p
[1] == ':') p
+= 2;
99 while (*p
== '\\') p
++; /* skip drive root */
100 while ((p
= strchr(p
, '\\')) != NULL
)
103 memcpy(path
, DirPath
, n
);
105 if( !CreateDirectoryA(path
, NULL
) &&
106 (GetLastError() != ERROR_ALREADY_EXISTS
))
110 if (GetLastError() == ERROR_ALREADY_EXISTS
)
111 SetLastError(ERROR_SUCCESS
);
116 /******************************************************************
117 * SymMatchFileName (DBGHELP.@)
120 BOOL WINAPI
SymMatchFileName(char* file
, char* match
,
121 char** filestop
, char** matchstop
)
126 TRACE("(%s %s %p %p)\n", file
, match
, filestop
, matchstop
);
128 fptr
= file
+ strlen(file
) - 1;
129 mptr
= match
+ strlen(match
) - 1;
131 while (fptr
>= file
&& mptr
>= match
)
133 if (toupper(*fptr
) != toupper(*mptr
) && !(is_sep(*fptr
) && is_sep(*mptr
)))
137 if (filestop
) *filestop
= fptr
;
138 if (matchstop
) *matchstop
= mptr
;
140 return mptr
== match
- 1;
143 static BOOL
do_search(const char* file
, char* buffer
,
144 PENUMDIRTREE_CALLBACK cb
, void* user
)
151 pos
= strlen(buffer
);
152 if (buffer
[pos
- 1] != '\\') buffer
[pos
++] = '\\';
153 strcpy(buffer
+ pos
, "*.*");
154 if ((h
= FindFirstFileA(buffer
, &fd
)) == INVALID_HANDLE_VALUE
)
156 /* doc doesn't specify how the tree is enumerated...
157 * doing a depth first based on, but may be wrong
161 if (!strcmp(fd
.cFileName
, ".") || !strcmp(fd
.cFileName
, "..")) continue;
163 strcpy(buffer
+ pos
, fd
.cFileName
);
164 if (fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
165 found
= do_search(file
, buffer
, cb
, user
);
166 else if (SymMatchFileName(buffer
, (char*)file
, NULL
, NULL
))
168 if (!cb
|| cb(buffer
, user
)) found
= TRUE
;
170 } while (!found
&& FindNextFileA(h
, &fd
));
171 if (!found
) buffer
[--pos
] = '\0';
177 /***********************************************************************
178 * SearchTreeForFile (DBGHELP.@)
180 BOOL WINAPI
SearchTreeForFile(LPSTR root
, LPSTR file
, LPSTR buffer
)
182 TRACE("(%s, %s, %p)\n",
183 debugstr_a(root
), debugstr_a(file
), buffer
);
184 strcpy(buffer
, root
);
185 return do_search(file
, buffer
, NULL
, NULL
);
188 /******************************************************************
189 * EnumDirTree (DBGHELP.@)
193 BOOL WINAPI
EnumDirTree(HANDLE hProcess
, PCSTR root
, PCSTR file
,
194 LPSTR buffer
, PENUMDIRTREE_CALLBACK cb
, void* user
)
196 TRACE("(%p %s %s %p %p %p)\n", hProcess
, root
, file
, buffer
, cb
, user
);
198 strcpy(buffer
, root
);
199 return do_search(file
, buffer
, cb
, user
);
208 PFINDFILEINPATHCALLBACK cb
;
212 static BOOL CALLBACK
sffip_cb(LPCSTR buffer
, void* user
)
214 struct sffip
* s
= (struct sffip
*)user
;
216 /* FIXME: should check that id/two/three match the file pointed
219 /* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
220 * convention to stop/continue enumeration. sigh.
222 return !(s
->cb
)((char*)buffer
, s
->user
);
225 /******************************************************************
226 * SymFindFileInPath (DBGHELP.@)
229 BOOL WINAPI
SymFindFileInPath(HANDLE hProcess
, LPSTR searchPath
, LPSTR file
,
230 PVOID id
, DWORD two
, DWORD three
, DWORD flags
,
231 LPSTR buffer
, PFINDFILEINPATHCALLBACK cb
,
235 struct process
* pcs
= process_find_by_handle(hProcess
);
239 TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
240 hProcess
, searchPath
, file
, id
, two
, three
, flags
,
243 if (!pcs
) return FALSE
;
244 if (!searchPath
) searchPath
= pcs
->search_path
;
253 file
= file_name(file
);
257 ptr
= strchr(searchPath
, ';');
260 memcpy(tmp
, searchPath
, ptr
- searchPath
);
261 tmp
[ptr
- searchPath
] = 0;
262 searchPath
= ptr
+ 1;
266 strcpy(tmp
, searchPath
);
269 if (EnumDirTree(hProcess
, tmp
, file
, buffer
, sffip_cb
, &s
)) return TRUE
;