advapi32: Cast-qual warnings fix.
[wine/hacks.git] / dlls / dbghelp / path.c
blobf2970116266bde91ce52edf29f7606e225a6de8f
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "dbghelp_private.h"
27 #include "winnls.h"
28 #include "winreg.h"
29 #include "winternl.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
34 static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
36 static inline const char* file_name(const char* str)
38 const char* p;
40 for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
41 return p + 1;
44 /******************************************************************
45 * FindDebugInfoFile (DBGHELP.@)
48 HANDLE WINAPI FindDebugInfoFile(PCSTR FileName, PCSTR SymbolPath, PSTR DebugFilePath)
50 HANDLE h;
52 h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
53 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
54 if (h == INVALID_HANDLE_VALUE)
56 if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
57 return NULL;
58 h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
59 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
61 return (h == INVALID_HANDLE_VALUE) ? NULL : h;
64 /******************************************************************
65 * FindDebugInfoFileEx (DBGHELP.@)
68 HANDLE WINAPI FindDebugInfoFileEx(PCSTR FileName, PCSTR SymbolPath,
69 PSTR DebugFilePath,
70 PFIND_DEBUG_FILE_CALLBACK Callback,
71 PVOID CallerData)
73 FIXME("(%s %s %p %p %p): stub\n",
74 FileName, SymbolPath, DebugFilePath, Callback, CallerData);
75 return NULL;
78 /******************************************************************
79 * FindExecutableImage (DBGHELP.@)
82 HANDLE WINAPI FindExecutableImage(PCSTR FileName, PCSTR SymbolPath, PSTR ImageFilePath)
84 HANDLE h;
85 if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
86 return NULL;
87 h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
88 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
89 return (h == INVALID_HANDLE_VALUE) ? NULL : h;
92 /***********************************************************************
93 * MakeSureDirectoryPathExists (DBGHELP.@)
95 BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
97 char path[MAX_PATH];
98 const char *p = DirPath;
99 int n;
101 if (p[0] && p[1] == ':') p += 2;
102 while (*p == '\\') p++; /* skip drive root */
103 while ((p = strchr(p, '\\')) != NULL)
105 n = p - DirPath + 1;
106 memcpy(path, DirPath, n);
107 path[n] = '\0';
108 if( !CreateDirectoryA(path, NULL) &&
109 (GetLastError() != ERROR_ALREADY_EXISTS))
110 return FALSE;
111 p++;
113 if (GetLastError() == ERROR_ALREADY_EXISTS)
114 SetLastError(ERROR_SUCCESS);
116 return TRUE;
119 /******************************************************************
120 * SymMatchFileName (DBGHELP.@)
123 BOOL WINAPI SymMatchFileName(char* file, char* match,
124 char** filestop, char** matchstop)
126 char* fptr;
127 char* mptr;
129 TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
131 fptr = file + strlen(file) - 1;
132 mptr = match + strlen(match) - 1;
134 while (fptr >= file && mptr >= match)
136 if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
137 break;
138 fptr--; mptr--;
140 if (filestop) *filestop = fptr;
141 if (matchstop) *matchstop = mptr;
143 return mptr == match - 1;
146 static BOOL do_search(const char* file, char* buffer, BOOL recurse,
147 PENUMDIRTREE_CALLBACK cb, void* user)
149 HANDLE h;
150 WIN32_FIND_DATAA fd;
151 unsigned pos;
152 BOOL found = FALSE;
154 pos = strlen(buffer);
155 if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
156 strcpy(buffer + pos, "*.*");
157 if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
158 return FALSE;
159 /* doc doesn't specify how the tree is enumerated...
160 * doing a depth first based on, but may be wrong
164 if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
166 strcpy(buffer + pos, fd.cFileName);
167 if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
168 found = do_search(file, buffer, TRUE, cb, user);
169 else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
171 if (!cb || cb(buffer, user)) found = TRUE;
173 } while (!found && FindNextFileA(h, &fd));
174 if (!found) buffer[--pos] = '\0';
175 FindClose(h);
177 return found;
180 /***********************************************************************
181 * SearchTreeForFile (DBGHELP.@)
183 BOOL WINAPI SearchTreeForFile(PCSTR root, PCSTR file, PSTR buffer)
185 TRACE("(%s, %s, %p)\n",
186 debugstr_a(root), debugstr_a(file), buffer);
187 strcpy(buffer, root);
188 return do_search(file, buffer, TRUE, NULL, NULL);
191 /******************************************************************
192 * EnumDirTree (DBGHELP.@)
196 BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
197 LPSTR buffer, PENUMDIRTREE_CALLBACK cb, PVOID user)
199 TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
201 strcpy(buffer, root);
202 return do_search(file, buffer, TRUE, cb, user);
205 struct sffip
207 enum module_type kind;
208 /* pe: id -> DWORD:timestamp
209 * two -> size of image (from PE header)
210 * pdb: id -> PDB signature
211 * I think either DWORD:timestamp or GUID:guid depending on PDB version
212 * two -> PDB age ???
213 * elf: id -> DWORD:CRC 32 of ELF image (Wine only)
215 PVOID id;
216 DWORD two;
217 DWORD three;
218 DWORD flags;
219 PFINDFILEINPATHCALLBACK cb;
220 void* user;
223 /* checks that buffer (as found by matching the name) matches the info
224 * (information is based on file type)
225 * returns TRUE when file is found, FALSE to continue searching
226 * (NB this is the opposite conventions as for SymFindFileInPathProc)
228 static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
230 struct sffip* s = (struct sffip*)user;
231 DWORD size, checksum;
233 /* FIXME: should check that id/two/three match the file pointed
234 * by buffer
236 switch (s->kind)
238 case DMT_PE:
240 HANDLE hFile, hMap;
241 void* mapping;
242 DWORD timestamp;
244 timestamp = ~(DWORD_PTR)s->id;
245 size = ~s->two;
246 hFile = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ, NULL,
247 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
248 if (hFile == INVALID_HANDLE_VALUE) return FALSE;
249 if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
251 if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
253 IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping);
254 timestamp = nth->FileHeader.TimeDateStamp;
255 size = nth->OptionalHeader.SizeOfImage;
256 UnmapViewOfFile(mapping);
258 CloseHandle(hMap);
260 CloseHandle(hFile);
261 if (timestamp != (DWORD_PTR)s->id || size != s->two)
263 WARN("Found %s, but wrong size or timestamp\n", buffer);
264 return FALSE;
267 break;
268 case DMT_ELF:
269 if (elf_fetch_file_info(buffer, 0, &size, &checksum))
271 if (checksum != (DWORD_PTR)s->id)
273 WARN("Found %s, but wrong checksums: %08lx %08lx\n",
274 buffer, checksum, (DWORD_PTR)s->id);
275 return FALSE;
278 else
280 WARN("Couldn't read %s\n", buffer);
281 return FALSE;
283 break;
284 case DMT_PDB:
286 struct pdb_lookup pdb_lookup;
288 pdb_lookup.filename = buffer;
290 if (!pdb_fetch_file_info(&pdb_lookup)) return FALSE;
291 switch (pdb_lookup.kind)
293 case PDB_JG:
294 if (s->flags & SSRVOPT_GUIDPTR)
296 WARN("Found %s, but wrong PDB version\n", buffer);
297 return FALSE;
299 if (pdb_lookup.u.jg.timestamp != (DWORD_PTR)s->id)
301 WARN("Found %s, but wrong signature: %08lx %08lx\n",
302 buffer, pdb_lookup.u.jg.timestamp, (DWORD_PTR)s->id);
303 return FALSE;
305 break;
306 case PDB_DS:
307 if (!(s->flags & SSRVOPT_GUIDPTR))
309 WARN("Found %s, but wrong PDB version\n", buffer);
310 return FALSE;
312 if (memcmp(&pdb_lookup.u.ds.guid, (GUID*)s->id, sizeof(GUID)))
314 WARN("Found %s, but wrong GUID: %s %s\n",
315 buffer, debugstr_guid(&pdb_lookup.u.ds.guid),
316 debugstr_guid((GUID*)s->id));
317 return FALSE;
319 break;
321 if (pdb_lookup.age != s->two)
323 WARN("Found %s, but wrong age: %08lx %08lx\n",
324 buffer, pdb_lookup.age, s->two);
325 return FALSE;
328 break;
329 default:
330 FIXME("What the heck??\n");
331 return FALSE;
333 /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite
334 * convention to stop/continue enumeration. sigh.
336 return !(s->cb)((char*)buffer, s->user);
339 /******************************************************************
340 * SymFindFileInPath (DBGHELP.@)
343 BOOL WINAPI SymFindFileInPath(HANDLE hProcess, PCSTR inSearchPath, PCSTR full_path,
344 PVOID id, DWORD two, DWORD three, DWORD flags,
345 LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
346 PVOID user)
348 struct sffip s;
349 struct process* pcs = process_find_by_handle(hProcess);
350 char tmp[MAX_PATH];
351 char* ptr;
352 const char* filename;
353 const char* searchPath = inSearchPath;
355 TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
356 hProcess, searchPath, full_path, id, two, three, flags,
357 buffer, cb, user);
359 if (!pcs) return FALSE;
360 if (!searchPath)
362 unsigned len = WideCharToMultiByte(CP_ACP, 0, pcs->search_path, -1, NULL, 0, NULL, NULL);
363 char* buf;
365 searchPath = buf = HeapAlloc(GetProcessHeap(), 0, len);
366 if (!searchPath) return FALSE;
367 WideCharToMultiByte(CP_ACP, 0, pcs->search_path, -1, buf, len, NULL, NULL);
370 s.id = id;
371 s.two = two;
372 s.three = three;
373 s.flags = flags;
374 s.cb = cb;
375 s.user = user;
377 filename = file_name(full_path);
378 s.kind = module_get_type_by_name(filename);
380 /* first check full path to file */
381 if (sffip_cb(full_path, &s))
383 strcpy(buffer, full_path);
384 if (searchPath != inSearchPath)
385 HeapFree(GetProcessHeap(), 0, (char*)searchPath);
386 return TRUE;
389 while (searchPath)
391 ptr = strchr(searchPath, ';');
392 if (ptr)
394 memcpy(tmp, searchPath, ptr - searchPath);
395 tmp[ptr - searchPath] = 0;
396 searchPath = ptr + 1;
398 else
400 strcpy(tmp, searchPath);
401 searchPath = NULL;
403 if (do_search(filename, tmp, FALSE, sffip_cb, &s))
405 strcpy(buffer, tmp);
406 if (searchPath != inSearchPath)
407 HeapFree(GetProcessHeap(), 0, (char*)searchPath);
408 return TRUE;
411 if (searchPath != inSearchPath)
412 HeapFree(GetProcessHeap(), 0, (char*)searchPath);
413 return FALSE;