1 /* 2 * Copyright 2003, 2004, 2005 Martin Fuchs 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 20 // 21 // Explorer clone 22 // 23 // utility.cpp 24 // 25 // Martin Fuchs, 23.07.2003 26 // 27 28 29 #include <precomp.h> 30 31 //#include <shellapi.h> 32 33 #include <time.h> 34 #include <sstream> 35 36 37 DWORD WINAPI Thread::ThreadProc(void* para) 38 { 39 Thread* pThis = (Thread*) para; 40 41 int ret = pThis->Run(); 42 43 pThis->_alive = false; 44 45 return ret; 46 } 47 48 49 void CenterWindow(HWND hwnd) 50 { 51 RECT rt, prt; 52 GetWindowRect(hwnd, &rt); 53 54 DWORD style; 55 HWND owner = 0; 56 57 for(HWND wh=hwnd; (wh=GetWindow(wh,GW_OWNER))!=0; ) 58 if (((style=GetWindowStyle(wh))&WS_VISIBLE) && !(style&WS_MINIMIZE)) 59 {owner=wh; break;} 60 61 if (owner) 62 GetWindowRect(owner, &prt); 63 else 64 SystemParametersInfo(SPI_GETWORKAREA, 0, &prt, 0); //@@ GetDesktopWindow() w�re auch hilfreich. 65 66 SetWindowPos(hwnd, 0, (prt.left+prt.right+rt.left-rt.right)/2, 67 (prt.top+prt.bottom+rt.top-rt.bottom)/2, 0,0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); 68 69 MoveVisible(hwnd); 70 } 71 72 void MoveVisible(HWND hwnd) 73 { 74 RECT rc; 75 GetWindowRect(hwnd, &rc); 76 int left=rc.left, top=rc.top; 77 78 int xmax = GetSystemMetrics(SM_CXSCREEN); 79 int ymax = GetSystemMetrics(SM_CYSCREEN); 80 81 if (rc.left < 0) 82 rc.left = 0; 83 else if (rc.right > xmax) 84 if ((rc.left-=rc.right-xmax) < 0) 85 rc.left = 0; 86 87 if (rc.top < 0) 88 rc.top = 0; 89 else if (rc.bottom > ymax) 90 if ((rc.top-=rc.bottom-ymax) < 0) 91 rc.top = 0; 92 93 if (rc.left!=left || rc.top!=top) 94 SetWindowPos(hwnd, 0, rc.left,rc.top, 0,0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE); 95 } 96 97 98 void display_error(HWND hwnd, DWORD error) //@@ CONTEXT mit ausgeben -> display_error(HWND hwnd, const Exception& e) 99 { 100 PTSTR msg; 101 102 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 103 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) { 104 LOG(FmtString(TEXT("display_error(%#x): %s"), error, msg)); 105 106 SetLastError(0); 107 MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); 108 109 if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) 110 MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); 111 } else { 112 LOG(FmtString(TEXT("Unknown Error %#x"), error)); 113 114 FmtString msg(TEXT("Unknown Error %#x"), error); 115 116 SetLastError(0); 117 MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); 118 119 if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) 120 MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); 121 } 122 123 LocalFree(msg); 124 } 125 126 127 Context Context::s_main("-NO-CONTEXT-"); 128 Context* Context::s_current = &Context::s_main; 129 130 String Context::toString() const 131 { 132 String str = _ctx; 133 134 if (!_obj.empty()) 135 str.appendf(TEXT("\nObject: %s"), (LPCTSTR)_obj); 136 137 return str; 138 } 139 140 String Context::getStackTrace() const 141 { 142 ostringstream str; 143 144 str << "Context Trace:\n"; 145 146 for(const Context*p=this; p && p!=&s_main; p=p->_last) { 147 str << "- " << p->_ctx; 148 149 if (!p->_obj.empty()) 150 str << " obj=" << ANS(p->_obj); 151 152 str << '\n'; 153 } 154 155 return str.str(); 156 } 157 158 159 BOOL time_to_filetime(const time_t* t, FILETIME* ftime) 160 { 161 #if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER) 162 SYSTEMTIME stime; 163 struct tm tm_; 164 struct tm* tm = &tm_; 165 166 if (gmtime_s(tm, t) != 0) 167 return FALSE; 168 #else 169 struct tm* tm = gmtime(t); 170 SYSTEMTIME stime; 171 172 if (!tm) 173 return FALSE; 174 #endif 175 176 stime.wYear = tm->tm_year+1900; 177 stime.wMonth = tm->tm_mon+1; 178 stime.wDayOfWeek = (WORD)-1; 179 stime.wDay = tm->tm_mday; 180 stime.wHour = tm->tm_hour; 181 stime.wMinute = tm->tm_min; 182 stime.wSecond = tm->tm_sec; 183 stime.wMilliseconds = 0; 184 185 return SystemTimeToFileTime(&stime, ftime); 186 } 187 188 189 BOOL launch_file(HWND hwnd, LPCTSTR cmd, UINT nCmdShow, LPCTSTR parameters) 190 { 191 CONTEXT("launch_file()"); 192 193 HINSTANCE hinst = ShellExecute(hwnd, NULL/*operation*/, cmd, parameters, NULL/*dir*/, nCmdShow); 194 195 if ((INT_PTR)hinst <= 32) { 196 display_error(hwnd, GetLastError()); 197 return FALSE; 198 } 199 200 return TRUE; 201 } 202 203 #ifdef UNICODE 204 BOOL launch_fileA(HWND hwnd, LPSTR cmd, UINT nCmdShow, LPCSTR parameters) 205 { 206 HINSTANCE hinst = ShellExecuteA(hwnd, NULL/*operation*/, cmd, parameters, NULL/*dir*/, nCmdShow); 207 208 if ((INT_PTR)hinst <= 32) { 209 display_error(hwnd, GetLastError()); 210 return FALSE; 211 } 212 213 return TRUE; 214 } 215 #endif 216 217 218 /* search for already running instance */ 219 220 static int g_foundPrevInstance = 0; 221 222 static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lparam) 223 { 224 TCHAR cls[128]; 225 226 GetClassName(hwnd, cls, 128); 227 228 if (!lstrcmp(cls, (LPCTSTR)lparam)) { 229 g_foundPrevInstance++; 230 return FALSE; 231 } 232 233 return TRUE; 234 } 235 236 /* search for window of given class name to allow only one running instance */ 237 int find_window_class(LPCTSTR classname) 238 { 239 EnumWindows(EnumWndProc, (LPARAM)classname); 240 241 if (g_foundPrevInstance) 242 return 1; 243 244 return 0; 245 } 246 247 248 String get_windows_version_str() 249 { 250 OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; 251 BOOL osvie_val; 252 String str; 253 254 if (!(osvie_val = GetVersionEx((OSVERSIONINFO*)&osvi))) { 255 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 256 257 if (!GetVersionEx((OSVERSIONINFO*)&osvi)) 258 return TEXT("???"); 259 } 260 261 switch(osvi.dwPlatformId) { 262 case VER_PLATFORM_WIN32_NT: 263 #ifdef __REACTOS__ // This work around can be removed if ReactOS gets a unique version number. 264 str = TEXT("ReactOS"); 265 #else 266 if (osvi.dwMajorVersion <= 4) 267 str = TEXT("Microsoft Windows NT"); 268 else if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0) 269 str = TEXT("Microsoft Windows 2000"); 270 else if (osvi.dwMajorVersion==5 && osvi.dwMinorVersion==1) 271 str = TEXT("Microsoft Windows XP"); 272 #endif 273 274 if (osvie_val) { 275 if (osvi.wProductType == VER_NT_WORKSTATION) { 276 if (osvi.wSuiteMask & VER_SUITE_PERSONAL) 277 str += TEXT(" Personal"); 278 else 279 str += TEXT(" Professional"); 280 } else if (osvi.wProductType == VER_NT_SERVER) { 281 if (osvi.wSuiteMask & VER_SUITE_DATACENTER) 282 str += TEXT(" DataCenter Server"); 283 else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) 284 str += TEXT(" Advanced Server"); 285 else 286 str += TEXT(" Server"); 287 } else if (osvi.wProductType == VER_NT_DOMAIN_CONTROLLER) { 288 str += TEXT(" Domain Controller"); 289 } 290 } else { 291 TCHAR type[80]; 292 DWORD dwBufLen; 293 HKEY hkey; 294 295 if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hkey)) { 296 RegQueryValueEx(hkey, TEXT("ProductType"), NULL, NULL, (LPBYTE)type, &dwBufLen); 297 RegCloseKey(hkey); 298 299 if (!_tcsicmp(TEXT("WINNT"), type)) 300 str += TEXT(" Workstation"); 301 else if (!_tcsicmp(TEXT("LANMANNT"), type)) 302 str += TEXT(" Server"); 303 else if (!_tcsicmp(TEXT("SERVERNT"), type)) 304 str += TEXT(" Advanced Server"); 305 } 306 } 307 break; 308 309 case VER_PLATFORM_WIN32_WINDOWS: 310 if (osvi.dwMajorVersion>4 || 311 (osvi.dwMajorVersion==4 && osvi.dwMinorVersion>0)) { 312 if (osvi.dwMinorVersion == 90) 313 str = TEXT("Microsoft Windows ME"); 314 else 315 str = TEXT("Microsoft Windows 98"); 316 317 if (osvi.szCSDVersion[1] == 'A') 318 str += TEXT(" SE"); 319 } else { 320 str = TEXT("Microsoft Windows 95"); 321 322 if (osvi.szCSDVersion[1]=='B' || osvi.szCSDVersion[1]=='C') 323 str += TEXT(" OSR2"); 324 } 325 break; 326 327 case VER_PLATFORM_WIN32s: 328 str = TEXT("Microsoft Win32s"); 329 330 default: 331 return TEXT("???"); 332 } 333 334 String vstr; 335 336 if (osvi.dwMajorVersion <= 4) 337 vstr.printf(TEXT(" Version %d.%d %s Build %d"), 338 osvi.dwMajorVersion, osvi.dwMinorVersion, 339 osvi.szCSDVersion, osvi.dwBuildNumber&0xFFFF); 340 else 341 vstr.printf(TEXT(" %s (Build %d)"), osvi.szCSDVersion, osvi.dwBuildNumber&0xFFFF); 342 343 return str + vstr; 344 } 345 346 347 typedef void (WINAPI*RUNDLLPROC)(HWND hwnd, HINSTANCE hinst, LPCTSTR cmdline, DWORD nCmdShow); 348 349 BOOL RunDLL(HWND hwnd, LPCTSTR dllname, LPCSTR procname, LPCTSTR cmdline, UINT nCmdShow) 350 { 351 HMODULE hmod = LoadLibrary(dllname); 352 if (!hmod) 353 return FALSE; 354 355 /*TODO 356 <Windows NT/2000> 357 It is possible to create a Unicode version of the function. 358 Rundll32 first tries to find a function named EntryPointW. 359 If it cannot find this function, it tries EntryPointA, then EntryPoint. 360 To create a DLL that supports ANSI on Windows 95/98/Me and Unicode otherwise, 361 export two functions: EntryPointW and EntryPoint. 362 */ 363 RUNDLLPROC proc = (RUNDLLPROC)GetProcAddress(hmod, procname); 364 if (!proc) { 365 FreeLibrary(hmod); 366 return FALSE; 367 } 368 369 proc(hwnd, hmod, cmdline, nCmdShow); 370 371 FreeLibrary(hmod); 372 373 return TRUE; 374 } 375 376 377 #ifdef UNICODE 378 #define CONTROL_RUNDLL "Control_RunDLLW" 379 #else 380 #define CONTROL_RUNDLL "Control_RunDLLA" 381 #endif 382 383 BOOL launch_cpanel(HWND hwnd, LPCTSTR applet) 384 { 385 TCHAR parameters[MAX_PATH]; 386 387 _tcscpy(parameters, TEXT("shell32.dll,Control_RunDLL ")); 388 _tcscat(parameters, applet); 389 390 return ((INT_PTR)ShellExecute(hwnd, TEXT("open"), TEXT("rundll32.exe"), parameters, NULL, SW_SHOWDEFAULT) > 32); 391 } 392 393 394 BOOL RecursiveCreateDirectory(LPCTSTR path_in) 395 { 396 TCHAR path[MAX_PATH], hole_path[MAX_PATH]; 397 398 _tcscpy(hole_path, path_in); 399 400 int drv_len = 0; 401 LPCTSTR d; 402 403 for(d=hole_path; *d && *d!='/' && *d!='\\'; ++d) { 404 ++drv_len; 405 406 if (*d == ':') 407 break; 408 } 409 410 LPTSTR dir = hole_path + drv_len; 411 412 int l; 413 LPTSTR p = hole_path + (l=_tcslen(hole_path)); 414 415 while(--p>=hole_path && (*p=='/' || *p=='\\')) 416 *p = '\0'; 417 418 WIN32_FIND_DATA w32fd; 419 420 HANDLE hFind = FindFirstFile(hole_path, &w32fd); 421 422 if (hFind == INVALID_HANDLE_VALUE) { 423 _tcsncpy(path, hole_path, drv_len); 424 int i = drv_len; 425 426 for(p=dir; *p=='/'||*p=='\\'; p++) 427 path[i++] = *p++; 428 429 for(; i<l; i++) { 430 memcpy(path, hole_path, i*sizeof(TCHAR)); 431 432 for(; hole_path[i] && hole_path[i]!='/' && hole_path[i]!='\\'; i++) 433 path[i] = hole_path[i]; 434 435 path[i] = '\0'; 436 437 hFind = FindFirstFile(path, &w32fd); 438 439 if (hFind != INVALID_HANDLE_VALUE) 440 FindClose(hFind); 441 else { 442 LOG(FmtString(TEXT("CreateDirectory(\"%s\")"), path)); 443 444 if (!CreateDirectory(path, 0)) 445 return FALSE; 446 } 447 } 448 } else 449 FindClose(hFind); 450 451 return TRUE; 452 } 453 454 455 DWORD RegGetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD def) 456 { 457 HKEY hkey; 458 DWORD ret; 459 460 if (!RegOpenKey(root, path, &hkey)) { 461 DWORD len = sizeof(ret); 462 463 if (RegQueryValueEx(hkey, valueName, 0, NULL, (LPBYTE)&ret, &len)) 464 ret = def; 465 466 RegCloseKey(hkey); 467 468 return ret; 469 } else 470 return def; 471 } 472 473 474 BOOL RegSetDWORDValue(HKEY root, LPCTSTR path, LPCTSTR valueName, DWORD value) 475 { 476 HKEY hkey; 477 BOOL ret = FALSE; 478 479 if (!RegOpenKey(root, path, &hkey)) { 480 ret = RegSetValueEx(hkey, valueName, 0, REG_DWORD, (LPBYTE)&value, sizeof(value)); 481 482 RegCloseKey(hkey); 483 } 484 485 return ret; 486 } 487 488 489 BOOL exists_path(LPCTSTR path) 490 { 491 WIN32_FIND_DATA fd; 492 493 HANDLE hfind = FindFirstFile(path, &fd); 494 495 if (hfind != INVALID_HANDLE_VALUE) { 496 FindClose(hfind); 497 498 return TRUE; 499 } else 500 return FALSE; 501 } 502 503 504 bool SplitFileSysURL(LPCTSTR url, String& dir_out, String& fname_out) 505 { 506 if (!_tcsnicmp(url, TEXT("file://"), 7)) { 507 url += 7; 508 509 // remove third slash in front of drive characters 510 if (*url == '/') 511 ++url; 512 } 513 514 if (exists_path(url)) { 515 TCHAR path[_MAX_PATH]; 516 517 // convert slashes to back slashes 518 GetFullPathName(url, COUNTOF(path), path, NULL); 519 520 if (GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY) 521 fname_out.erase(); 522 else { 523 TCHAR drv[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; 524 525 _tsplitpath_s(path, drv, COUNTOF(drv), dir, COUNTOF(dir), fname, COUNTOF(fname), ext, COUNTOF(ext)); 526 _stprintf(path, TEXT("%s%s"), drv, dir); 527 528 fname_out.printf(TEXT("%s%s"), fname, ext); 529 } 530 531 dir_out = path; 532 533 return true; 534 } else 535 return false; 536 } 537