VK_0-9 and VK_A-Z are not defined in the Windows headers, removed them
[wine] / dlls / dbghelp / path.c
1 /*
2  * File path.c - managing path in debugging environments
3  *
4  * Copyright (C) 2004, Eric Pouech
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "dbghelp_private.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
30
31 static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
32
33 static inline char* file_name(char* str)
34 {
35     char*       p;
36
37     for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
38     return p + 1;
39 }
40
41 /******************************************************************
42  *              FindDebugInfoFile (DBGHELP.@)
43  *
44  */
45 HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePath)
46 {
47     HANDLE      h;
48
49     h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
50                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
51     if (h == INVALID_HANDLE_VALUE)
52     {
53         if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
54             return NULL;
55         h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
56                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
57     }
58     return (h == INVALID_HANDLE_VALUE) ? NULL : h;
59 }
60  
61 /******************************************************************
62  *              FindDebugInfoFileEx (DBGHELP.@)
63  *
64  */
65 HANDLE WINAPI FindDebugInfoFileEx(PSTR FileName, PSTR SymbolPath,
66                                   PSTR DebugFilePath, 
67                                   PFIND_DEBUG_FILE_CALLBACK Callback,
68                                   PVOID CallerData)
69 {
70     FIXME("(%s %s %p %p %p): stub\n", 
71           FileName, SymbolPath, DebugFilePath, Callback, CallerData);
72     return NULL;
73 }
74
75 /******************************************************************
76  *              FindExecutableImage (DBGHELP.@)
77  *
78  */
79 HANDLE WINAPI FindExecutableImage(PSTR FileName, PSTR SymbolPath, PSTR ImageFilePath)
80 {
81     HANDLE h;
82     if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
83         return 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;
87 }
88
89 /***********************************************************************
90  *           MakeSureDirectoryPathExists (DBGHELP.@)
91  */
92 BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
93 {
94     char path[MAX_PATH];
95     const char *p = DirPath;
96     int  n;
97
98     if (p[0] && p[1] == ':') p += 2;
99     while (*p == '\\') p++; /* skip drive root */
100     while ((p = strchr(p, '\\')) != NULL)
101     {
102        n = p - DirPath + 1;
103        memcpy(path, DirPath, n);
104        path[n] = '\0';
105        if( !CreateDirectoryA(path, NULL)            &&
106            (GetLastError() != ERROR_ALREADY_EXISTS))
107            return FALSE;
108        p++;
109     }
110     if (GetLastError() == ERROR_ALREADY_EXISTS)
111        SetLastError(ERROR_SUCCESS);
112
113     return TRUE;
114 }
115
116 /******************************************************************
117  *              SymMatchFileName (DBGHELP.@)
118  *
119  */
120 BOOL WINAPI SymMatchFileName(char* file, char* match,
121                              char** filestop, char** matchstop)
122 {
123     char*       fptr;
124     char*       mptr;
125
126     TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
127
128     fptr = file + strlen(file) - 1;
129     mptr = match + strlen(match) - 1;
130
131     while (fptr >= file && mptr >= match)
132     {
133         if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
134             break;
135         fptr--; mptr--;
136     }
137     if (filestop) *filestop = fptr;
138     if (matchstop) *matchstop = mptr;
139
140     return mptr == match - 1;
141 }
142
143 static BOOL do_search(const char* file, char* buffer,
144                       PENUMDIRTREE_CALLBACK cb, void* user)
145 {
146     HANDLE              h;
147     WIN32_FIND_DATAA    fd;
148     unsigned            pos;
149     BOOL                found = FALSE;
150
151     pos = strlen(buffer);
152     if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
153     strcpy(buffer + pos, "*.*");
154     if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
155         return FALSE;
156     /* doc doesn't specify how the tree is enumerated... 
157      * doing a depth first based on, but may be wrong
158      */
159     do
160     {
161         if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
162
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))
167         {
168             if (!cb || cb(buffer, user)) found = TRUE;
169         }
170     } while (!found && FindNextFileA(h, &fd));
171     if (!found) buffer[--pos] = '\0';
172     FindClose(h);
173
174     return found;
175 }
176
177 /***********************************************************************
178  *           SearchTreeForFile (DBGHELP.@)
179  */
180 BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
181 {
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);
186 }
187
188 /******************************************************************
189  *              EnumDirTree (DBGHELP.@)
190  *
191  *
192  */
193 BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
194                         LPSTR buffer, PENUMDIRTREE_CALLBACK cb, PVOID user)
195 {
196     TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
197
198     strcpy(buffer, root);
199     return do_search(file, buffer, cb, user);
200 }
201
202 struct sffip
203 {
204     PVOID                       id;
205     DWORD                       two;
206     DWORD                       three;
207     DWORD                       flags;
208     PFINDFILEINPATHCALLBACK     cb;
209     void*                       user;
210 };
211
212 static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
213 {
214     struct sffip*       s = (struct sffip*)user;
215
216     /* FIXME: should check that id/two/three match the file pointed
217      * by buffer
218      */
219     /* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
220      * convention to stop/continue enumeration. sigh.
221      */
222     return !(s->cb)((char*)buffer, s->user);
223 }
224
225 /******************************************************************
226  *              SymFindFileInPath (DBGHELP.@)
227  *
228  */
229 BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
230                               PVOID id, DWORD two, DWORD three, DWORD flags,
231                               LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
232                               PVOID user)
233 {
234     struct sffip        s;
235     struct process*     pcs = process_find_by_handle(hProcess);
236     char                tmp[MAX_PATH];
237     char*               ptr;
238
239     TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
240           hProcess, searchPath, file, id, two, three, flags, 
241           buffer, cb, user);
242
243     if (!pcs) return FALSE;
244     if (!searchPath) searchPath = pcs->search_path;
245
246     s.id = id;
247     s.two = two;
248     s.three = three;
249     s.flags = flags;
250     s.cb = cb;
251     s.user = user;
252
253     file = file_name(file);
254
255     while (searchPath)
256     {
257         ptr = strchr(searchPath, ';');
258         if (ptr)
259         {
260             memcpy(tmp, searchPath, ptr - searchPath);
261             tmp[ptr - searchPath] = 0;
262             searchPath = ptr + 1;
263         }
264         else
265         {
266             strcpy(tmp, searchPath);
267             searchPath = NULL;
268         }
269         if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
270     }
271     return FALSE;
272 }