Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpath.c
Go to the documentation of this file.
00001 /* 00002 * File path.c - managing path in debugging environments 00003 * 00004 * Copyright (C) 2004,2008, Eric Pouech 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 #include <stdlib.h> 00023 #include <stdio.h> 00024 #include <string.h> 00025 00026 #include "dbghelp_private.h" 00027 #include "winnls.h" 00028 #include "winternl.h" 00029 #include "wine/debug.h" 00030 00031 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 00032 00033 static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';} 00034 static inline BOOL is_sepW(WCHAR ch) {return ch == '/' || ch == '\\';} 00035 00036 static inline const char* file_name(const char* str) 00037 { 00038 const char* p; 00039 00040 for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--); 00041 return p + 1; 00042 } 00043 00044 static inline const WCHAR* file_nameW(const WCHAR* str) 00045 { 00046 const WCHAR* p; 00047 00048 for (p = str + strlenW(str) - 1; p >= str && !is_sepW(*p); p--); 00049 return p + 1; 00050 } 00051 00052 /****************************************************************** 00053 * FindDebugInfoFile (DBGHELP.@) 00054 * 00055 */ 00056 HANDLE WINAPI FindDebugInfoFile(PCSTR FileName, PCSTR SymbolPath, PSTR DebugFilePath) 00057 { 00058 HANDLE h; 00059 00060 h = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, 00061 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00062 if (h == INVALID_HANDLE_VALUE) 00063 { 00064 if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL)) 00065 return NULL; 00066 h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, 00067 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00068 } 00069 return (h == INVALID_HANDLE_VALUE) ? NULL : h; 00070 } 00071 00072 /****************************************************************** 00073 * FindDebugInfoFileEx (DBGHELP.@) 00074 * 00075 */ 00076 HANDLE WINAPI FindDebugInfoFileEx(PCSTR FileName, PCSTR SymbolPath, 00077 PSTR DebugFilePath, 00078 PFIND_DEBUG_FILE_CALLBACK Callback, 00079 PVOID CallerData) 00080 { 00081 FIXME("(%s %s %p %p %p): stub\n", 00082 debugstr_a(FileName), debugstr_a(SymbolPath), debugstr_a(DebugFilePath), Callback, CallerData); 00083 return NULL; 00084 } 00085 00086 /****************************************************************** 00087 * FindExecutableImageExW (DBGHELP.@) 00088 * 00089 */ 00090 HANDLE WINAPI FindExecutableImageExW(PCWSTR FileName, PCWSTR SymbolPath, PWSTR ImageFilePath, 00091 PFIND_EXE_FILE_CALLBACKW Callback, PVOID user) 00092 { 00093 HANDLE h; 00094 00095 if (Callback) FIXME("Unsupported callback yet\n"); 00096 if (!SearchPathW(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL)) 00097 return NULL; 00098 h = CreateFileW(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, 00099 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00100 return (h == INVALID_HANDLE_VALUE) ? NULL : h; 00101 } 00102 00103 /****************************************************************** 00104 * FindExecutableImageEx (DBGHELP.@) 00105 * 00106 */ 00107 HANDLE WINAPI FindExecutableImageEx(PCSTR FileName, PCSTR SymbolPath, PSTR ImageFilePath, 00108 PFIND_EXE_FILE_CALLBACK Callback, PVOID user) 00109 { 00110 HANDLE h; 00111 00112 if (Callback) FIXME("Unsupported callback yet\n"); 00113 if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL)) 00114 return NULL; 00115 h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, 00116 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00117 return (h == INVALID_HANDLE_VALUE) ? NULL : h; 00118 } 00119 00120 /****************************************************************** 00121 * FindExecutableImage (DBGHELP.@) 00122 * 00123 */ 00124 HANDLE WINAPI FindExecutableImage(PCSTR FileName, PCSTR SymbolPath, PSTR ImageFilePath) 00125 { 00126 return FindExecutableImageEx(FileName, SymbolPath, ImageFilePath, NULL, NULL); 00127 } 00128 00129 /*********************************************************************** 00130 * MakeSureDirectoryPathExists (DBGHELP.@) 00131 */ 00132 BOOL WINAPI MakeSureDirectoryPathExists(PCSTR DirPath) 00133 { 00134 char path[MAX_PATH]; 00135 const char *p = DirPath; 00136 int n; 00137 00138 if (p[0] && p[1] == ':') p += 2; 00139 while (*p == '\\') p++; /* skip drive root */ 00140 while ((p = strchr(p, '\\')) != NULL) 00141 { 00142 n = p - DirPath + 1; 00143 memcpy(path, DirPath, n); 00144 path[n] = '\0'; 00145 if( !CreateDirectoryA(path, NULL) && 00146 (GetLastError() != ERROR_ALREADY_EXISTS)) 00147 return FALSE; 00148 p++; 00149 } 00150 if (GetLastError() == ERROR_ALREADY_EXISTS) 00151 SetLastError(ERROR_SUCCESS); 00152 00153 return TRUE; 00154 } 00155 00156 /****************************************************************** 00157 * SymMatchFileNameW (DBGHELP.@) 00158 * 00159 */ 00160 BOOL WINAPI SymMatchFileNameW(PCWSTR file, PCWSTR match, 00161 PWSTR* filestop, PWSTR* matchstop) 00162 { 00163 PCWSTR fptr; 00164 PCWSTR mptr; 00165 00166 TRACE("(%s %s %p %p)\n", 00167 debugstr_w(file), debugstr_w(match), filestop, matchstop); 00168 00169 fptr = file + strlenW(file) - 1; 00170 mptr = match + strlenW(match) - 1; 00171 00172 while (fptr >= file && mptr >= match) 00173 { 00174 if (toupperW(*fptr) != toupperW(*mptr) && !(is_sepW(*fptr) && is_sepW(*mptr))) 00175 break; 00176 fptr--; mptr--; 00177 } 00178 if (filestop) *filestop = (PWSTR)fptr; 00179 if (matchstop) *matchstop = (PWSTR)mptr; 00180 00181 return mptr == match - 1; 00182 } 00183 00184 /****************************************************************** 00185 * SymMatchFileName (DBGHELP.@) 00186 * 00187 */ 00188 BOOL WINAPI SymMatchFileName(PCSTR file, PCSTR match, 00189 PSTR* filestop, PSTR* matchstop) 00190 { 00191 PCSTR fptr; 00192 PCSTR mptr; 00193 00194 TRACE("(%s %s %p %p)\n", debugstr_a(file), debugstr_a(match), filestop, matchstop); 00195 00196 fptr = file + strlen(file) - 1; 00197 mptr = match + strlen(match) - 1; 00198 00199 while (fptr >= file && mptr >= match) 00200 { 00201 if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr))) 00202 break; 00203 fptr--; mptr--; 00204 } 00205 if (filestop) *filestop = (PSTR)fptr; 00206 if (matchstop) *matchstop = (PSTR)mptr; 00207 00208 return mptr == match - 1; 00209 } 00210 00211 static BOOL do_searchW(PCWSTR file, PWSTR buffer, BOOL recurse, 00212 PENUMDIRTREE_CALLBACKW cb, PVOID user) 00213 { 00214 HANDLE h; 00215 WIN32_FIND_DATAW fd; 00216 unsigned pos; 00217 BOOL found = FALSE; 00218 static const WCHAR S_AllW[] = {'*','.','*','\0'}; 00219 static const WCHAR S_DotW[] = {'.','\0'}; 00220 static const WCHAR S_DotDotW[] = {'.','.','\0'}; 00221 00222 pos = strlenW(buffer); 00223 if (buffer[pos - 1] != '\\') buffer[pos++] = '\\'; 00224 strcpyW(buffer + pos, S_AllW); 00225 if ((h = FindFirstFileW(buffer, &fd)) == INVALID_HANDLE_VALUE) 00226 return FALSE; 00227 /* doc doesn't specify how the tree is enumerated... 00228 * doing a depth first based on, but may be wrong 00229 */ 00230 do 00231 { 00232 if (!strcmpW(fd.cFileName, S_DotW) || !strcmpW(fd.cFileName, S_DotDotW)) continue; 00233 00234 strcpyW(buffer + pos, fd.cFileName); 00235 if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 00236 found = do_searchW(file, buffer, TRUE, cb, user); 00237 else if (SymMatchFileNameW(buffer, file, NULL, NULL)) 00238 { 00239 if (!cb || cb(buffer, user)) found = TRUE; 00240 } 00241 } while (!found && FindNextFileW(h, &fd)); 00242 if (!found) buffer[--pos] = '\0'; 00243 FindClose(h); 00244 00245 return found; 00246 } 00247 00248 /*********************************************************************** 00249 * SearchTreeForFileW (DBGHELP.@) 00250 */ 00251 BOOL WINAPI SearchTreeForFileW(PCWSTR root, PCWSTR file, PWSTR buffer) 00252 { 00253 TRACE("(%s, %s, %p)\n", 00254 debugstr_w(root), debugstr_w(file), buffer); 00255 strcpyW(buffer, root); 00256 return do_searchW(file, buffer, TRUE, NULL, NULL); 00257 } 00258 00259 /*********************************************************************** 00260 * SearchTreeForFile (DBGHELP.@) 00261 */ 00262 BOOL WINAPI SearchTreeForFile(PCSTR root, PCSTR file, PSTR buffer) 00263 { 00264 WCHAR rootW[MAX_PATH]; 00265 WCHAR fileW[MAX_PATH]; 00266 WCHAR bufferW[MAX_PATH]; 00267 BOOL ret; 00268 00269 MultiByteToWideChar(CP_ACP, 0, root, -1, rootW, MAX_PATH); 00270 MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH); 00271 ret = SearchTreeForFileW(rootW, fileW, bufferW); 00272 if (ret) 00273 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); 00274 return ret; 00275 } 00276 00277 /****************************************************************** 00278 * EnumDirTreeW (DBGHELP.@) 00279 * 00280 * 00281 */ 00282 BOOL WINAPI EnumDirTreeW(HANDLE hProcess, PCWSTR root, PCWSTR file, 00283 PWSTR buffer, PENUMDIRTREE_CALLBACKW cb, PVOID user) 00284 { 00285 TRACE("(%p %s %s %p %p %p)\n", 00286 hProcess, debugstr_w(root), debugstr_w(file), buffer, cb, user); 00287 00288 strcpyW(buffer, root); 00289 return do_searchW(file, buffer, TRUE, cb, user); 00290 } 00291 00292 /****************************************************************** 00293 * EnumDirTree (DBGHELP.@) 00294 * 00295 * 00296 */ 00297 struct enum_dir_treeWA 00298 { 00299 PENUMDIRTREE_CALLBACK cb; 00300 void* user; 00301 char name[MAX_PATH]; 00302 }; 00303 00304 static BOOL CALLBACK enum_dir_treeWA(PCWSTR name, PVOID user) 00305 { 00306 struct enum_dir_treeWA* edt = user; 00307 00308 WideCharToMultiByte(CP_ACP, 0, name, -1, edt->name, MAX_PATH, NULL, NULL); 00309 return edt->cb(edt->name, edt->user); 00310 } 00311 00312 BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file, 00313 PSTR buffer, PENUMDIRTREE_CALLBACK cb, PVOID user) 00314 { 00315 WCHAR rootW[MAX_PATH]; 00316 WCHAR fileW[MAX_PATH]; 00317 WCHAR bufferW[MAX_PATH]; 00318 struct enum_dir_treeWA edt; 00319 BOOL ret; 00320 00321 edt.cb = cb; 00322 edt.user = user; 00323 MultiByteToWideChar(CP_ACP, 0, root, -1, rootW, MAX_PATH); 00324 MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH); 00325 if ((ret = EnumDirTreeW(hProcess, rootW, fileW, bufferW, enum_dir_treeWA, &edt))) 00326 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); 00327 return ret; 00328 } 00329 00330 struct sffip 00331 { 00332 PFINDFILEINPATHCALLBACKW cb; 00333 void* user; 00334 }; 00335 00336 /* checks that buffer (as found by matching the name) matches the info 00337 * (information is based on file type) 00338 * returns TRUE when file is found, FALSE to continue searching 00339 * (NB this is the opposite convention of SymFindFileInPathProc) 00340 */ 00341 static BOOL CALLBACK sffip_cb(PCWSTR buffer, PVOID user) 00342 { 00343 struct sffip* s = user; 00344 00345 if (!s->cb) return TRUE; 00346 /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite 00347 * convention to stop/continue enumeration. sigh. 00348 */ 00349 return !(s->cb)(buffer, s->user); 00350 } 00351 00352 /****************************************************************** 00353 * SymFindFileInPathW (DBGHELP.@) 00354 * 00355 */ 00356 BOOL WINAPI SymFindFileInPathW(HANDLE hProcess, PCWSTR searchPath, PCWSTR full_path, 00357 PVOID id, DWORD two, DWORD three, DWORD flags, 00358 PWSTR buffer, PFINDFILEINPATHCALLBACKW cb, 00359 PVOID user) 00360 { 00361 struct sffip s; 00362 struct process* pcs = process_find_by_handle(hProcess); 00363 WCHAR tmp[MAX_PATH]; 00364 WCHAR* ptr; 00365 const WCHAR* filename; 00366 00367 TRACE("(hProcess = %p, searchPath = %s, full_path = %s, id = %p, two = 0x%08x, three = 0x%08x, flags = 0x%08x, buffer = %p, cb = %p, user = %p)\n", 00368 hProcess, debugstr_w(searchPath), debugstr_w(full_path), 00369 id, two, three, flags, buffer, cb, user); 00370 00371 if (!pcs) return FALSE; 00372 if (!searchPath) searchPath = pcs->search_path; 00373 00374 s.cb = cb; 00375 s.user = user; 00376 00377 filename = file_nameW(full_path); 00378 00379 /* first check full path to file */ 00380 if (sffip_cb(full_path, &s)) 00381 { 00382 strcpyW(buffer, full_path); 00383 return TRUE; 00384 } 00385 00386 while (searchPath) 00387 { 00388 ptr = strchrW(searchPath, ';'); 00389 if (ptr) 00390 { 00391 memcpy(tmp, searchPath, (ptr - searchPath) * sizeof(WCHAR)); 00392 tmp[ptr - searchPath] = 0; 00393 searchPath = ptr + 1; 00394 } 00395 else 00396 { 00397 strcpyW(tmp, searchPath); 00398 searchPath = NULL; 00399 } 00400 if (do_searchW(filename, tmp, FALSE, sffip_cb, &s)) 00401 { 00402 strcpyW(buffer, tmp); 00403 return TRUE; 00404 } 00405 } 00406 return FALSE; 00407 } 00408 00409 /****************************************************************** 00410 * SymFindFileInPath (DBGHELP.@) 00411 * 00412 */ 00413 BOOL WINAPI SymFindFileInPath(HANDLE hProcess, PCSTR searchPath, PCSTR full_path, 00414 PVOID id, DWORD two, DWORD three, DWORD flags, 00415 PSTR buffer, PFINDFILEINPATHCALLBACK cb, 00416 PVOID user) 00417 { 00418 WCHAR searchPathW[MAX_PATH]; 00419 WCHAR full_pathW[MAX_PATH]; 00420 WCHAR bufferW[MAX_PATH]; 00421 struct enum_dir_treeWA edt; 00422 BOOL ret; 00423 00424 /* a PFINDFILEINPATHCALLBACK and a PENUMDIRTREE_CALLBACK have actually the 00425 * same signature & semantics, hence we can reuse the EnumDirTree W->A 00426 * conversion helper 00427 */ 00428 edt.cb = cb; 00429 edt.user = user; 00430 if (searchPath) 00431 MultiByteToWideChar(CP_ACP, 0, searchPath, -1, searchPathW, MAX_PATH); 00432 MultiByteToWideChar(CP_ACP, 0, full_path, -1, full_pathW, MAX_PATH); 00433 if ((ret = SymFindFileInPathW(hProcess, searchPath ? searchPathW : NULL, full_pathW, 00434 id, two, three, flags, 00435 bufferW, enum_dir_treeWA, &edt))) 00436 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); 00437 return ret; 00438 } 00439 00440 struct module_find 00441 { 00442 enum module_type kind; 00443 /* pe: dw1 DWORD:timestamp 00444 * dw2 size of image (from PE header) 00445 * pdb: guid PDB guid (if DS PDB file) 00446 * or dw1 PDB timestamp (if JG PDB file) 00447 * dw2 PDB age 00448 * elf: dw1 DWORD:CRC 32 of ELF image (Wine only) 00449 */ 00450 const GUID* guid; 00451 DWORD dw1; 00452 DWORD dw2; 00453 WCHAR filename[MAX_PATH]; 00454 unsigned matched; 00455 }; 00456 00457 /* checks that buffer (as found by matching the name) matches the info 00458 * (information is based on file type) 00459 * returns TRUE when file is found, FALSE to continue searching 00460 * (NB this is the opposite convention of SymFindFileInPathProc) 00461 */ 00462 static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) 00463 { 00464 struct module_find* mf = user; 00465 DWORD size, checksum, timestamp; 00466 unsigned matched = 0; 00467 00468 /* the matching weights: 00469 * +1 if a file with same name is found and is a decent file of expected type 00470 * +1 if first parameter and second parameter match 00471 */ 00472 00473 /* FIXME: should check that id/two match the file pointed 00474 * by buffer 00475 */ 00476 switch (mf->kind) 00477 { 00478 case DMT_PE: 00479 { 00480 HANDLE hFile, hMap; 00481 void* mapping; 00482 DWORD timestamp; 00483 00484 timestamp = ~mf->dw1; 00485 size = ~mf->dw2; 00486 hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, 00487 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00488 if (hFile == INVALID_HANDLE_VALUE) return FALSE; 00489 if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) 00490 { 00491 if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) 00492 { 00493 IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); 00494 00495 matched++; 00496 timestamp = nth->FileHeader.TimeDateStamp; 00497 size = nth->OptionalHeader.SizeOfImage; 00498 UnmapViewOfFile(mapping); 00499 } 00500 CloseHandle(hMap); 00501 } 00502 CloseHandle(hFile); 00503 if (timestamp != mf->dw1) 00504 WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); 00505 if (size != mf->dw2) 00506 WARN("Found %s, but wrong size\n", debugstr_w(buffer)); 00507 if (timestamp == mf->dw1 && size == mf->dw2) matched++; 00508 } 00509 break; 00510 case DMT_ELF: 00511 if (elf_fetch_file_info(buffer, 0, &size, &checksum)) 00512 { 00513 matched++; 00514 if (checksum == mf->dw1) matched++; 00515 else 00516 WARN("Found %s, but wrong checksums: %08x %08x\n", 00517 debugstr_w(buffer), checksum, mf->dw1); 00518 } 00519 else 00520 { 00521 WARN("Couldn't read %s\n", debugstr_w(buffer)); 00522 return FALSE; 00523 } 00524 break; 00525 case DMT_MACHO: 00526 if (macho_fetch_file_info(buffer, 0, &size, &checksum)) 00527 { 00528 matched++; 00529 if (checksum == mf->dw1) matched++; 00530 else 00531 WARN("Found %s, but wrong checksums: %08x %08x\n", 00532 debugstr_w(buffer), checksum, mf->dw1); 00533 } 00534 else 00535 { 00536 WARN("Couldn't read %s\n", debugstr_w(buffer)); 00537 return FALSE; 00538 } 00539 break; 00540 case DMT_PDB: 00541 { 00542 struct pdb_lookup pdb_lookup; 00543 char fn[MAX_PATH]; 00544 00545 WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); 00546 pdb_lookup.filename = fn; 00547 00548 if (mf->guid) 00549 { 00550 pdb_lookup.kind = PDB_DS; 00551 pdb_lookup.timestamp = 0; 00552 pdb_lookup.guid = *mf->guid; 00553 } 00554 else 00555 { 00556 pdb_lookup.kind = PDB_JG; 00557 pdb_lookup.timestamp = mf->dw1; 00558 /* pdb_loopkup.guid = */ 00559 } 00560 pdb_lookup.age = mf->dw2; 00561 00562 if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; 00563 } 00564 break; 00565 case DMT_DBG: 00566 { 00567 HANDLE hFile, hMap; 00568 void* mapping; 00569 00570 timestamp = ~mf->dw1; 00571 hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, 00572 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00573 if (hFile == INVALID_HANDLE_VALUE) return FALSE; 00574 if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) 00575 { 00576 if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) 00577 { 00578 const IMAGE_SEPARATE_DEBUG_HEADER* hdr; 00579 hdr = mapping; 00580 00581 if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) 00582 { 00583 matched++; 00584 timestamp = hdr->TimeDateStamp; 00585 } 00586 UnmapViewOfFile(mapping); 00587 } 00588 CloseHandle(hMap); 00589 } 00590 CloseHandle(hFile); 00591 if (timestamp == mf->dw1) matched++; 00592 else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); 00593 } 00594 break; 00595 default: 00596 FIXME("What the heck??\n"); 00597 return FALSE; 00598 } 00599 if (matched > mf->matched) 00600 { 00601 strcpyW(mf->filename, buffer); 00602 mf->matched = matched; 00603 } 00604 /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite 00605 * convention to stop/continue enumeration. sigh. 00606 */ 00607 return mf->matched == 2; 00608 } 00609 00610 BOOL path_find_symbol_file(const struct process* pcs, PCSTR full_path, 00611 const GUID* guid, DWORD dw1, DWORD dw2, PSTR buffer, 00612 BOOL* is_unmatched) 00613 { 00614 struct module_find mf; 00615 WCHAR full_pathW[MAX_PATH]; 00616 WCHAR tmp[MAX_PATH]; 00617 WCHAR* ptr; 00618 const WCHAR* filename; 00619 WCHAR* searchPath = pcs->search_path; 00620 00621 TRACE("(pcs = %p, full_path = %s, guid = %s, dw1 = 0x%08x, dw2 = 0x%08x, buffer = %p)\n", 00622 pcs, debugstr_a(full_path), debugstr_guid(guid), dw1, dw2, buffer); 00623 00624 mf.guid = guid; 00625 mf.dw1 = dw1; 00626 mf.dw2 = dw2; 00627 mf.matched = 0; 00628 00629 MultiByteToWideChar(CP_ACP, 0, full_path, -1, full_pathW, MAX_PATH); 00630 filename = file_nameW(full_pathW); 00631 mf.kind = module_get_type_by_name(filename); 00632 *is_unmatched = FALSE; 00633 00634 /* first check full path to file */ 00635 if (module_find_cb(full_pathW, &mf)) 00636 { 00637 WideCharToMultiByte(CP_ACP, 0, full_pathW, -1, buffer, MAX_PATH, NULL, NULL); 00638 return TRUE; 00639 } 00640 00641 while (searchPath) 00642 { 00643 ptr = strchrW(searchPath, ';'); 00644 if (ptr) 00645 { 00646 memcpy(tmp, searchPath, (ptr - searchPath) * sizeof(WCHAR)); 00647 tmp[ptr - searchPath] = '\0'; 00648 searchPath = ptr + 1; 00649 } 00650 else 00651 { 00652 strcpyW(tmp, searchPath); 00653 searchPath = NULL; 00654 } 00655 if (do_searchW(filename, tmp, FALSE, module_find_cb, &mf)) 00656 { 00657 /* return first fully matched file */ 00658 WideCharToMultiByte(CP_ACP, 0, tmp, -1, buffer, MAX_PATH, NULL, NULL); 00659 return TRUE; 00660 } 00661 } 00662 /* if no fully matching file is found, return the best matching file if any */ 00663 if ((dbghelp_options & SYMOPT_LOAD_ANYTHING) && mf.matched) 00664 { 00665 WideCharToMultiByte(CP_ACP, 0, mf.filename, -1, buffer, MAX_PATH, NULL, NULL); 00666 *is_unmatched = TRUE; 00667 return TRUE; 00668 } 00669 return FALSE; 00670 } Generated on Fri May 25 2012 04:16:31 for ReactOS by
1.7.6.1
|