00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../../stdafx.h"
00013 #include "../../debug.h"
00014 #include "../../gfx_func.h"
00015 #include "../../textbuf_gui.h"
00016 #include "../../fileio_func.h"
00017 #include "../../fios.h"
00018 #include <windows.h>
00019 #include <fcntl.h>
00020 #include <regstr.h>
00021 #include <shlobj.h>
00022 #include <Shellapi.h>
00023 #include "win32.h"
00024 #include "../../core/alloc_func.hpp"
00025 #include "../../openttd.h"
00026 #include "../../core/random_func.hpp"
00027 #include "../../string_func.h"
00028 #include "../../crashlog.h"
00029 #include <errno.h>
00030 #include <sys/stat.h>
00031
00032 static bool _has_console;
00033 static bool _cursor_disable = true;
00034 static bool _cursor_visible = true;
00035
00036 bool MyShowCursor(bool show, bool toggle)
00037 {
00038 if (toggle) _cursor_disable = !_cursor_disable;
00039 if (_cursor_disable) return show;
00040 if (_cursor_visible == show) return show;
00041
00042 _cursor_visible = show;
00043 ShowCursor(show);
00044
00045 return !show;
00046 }
00047
00053 bool LoadLibraryList(Function proc[], const char *dll)
00054 {
00055 while (*dll != '\0') {
00056 HMODULE lib;
00057 lib = LoadLibrary(MB_TO_WIDE(dll));
00058
00059 if (lib == NULL) return false;
00060 for (;;) {
00061 FARPROC p;
00062
00063 while (*dll++ != '\0') { }
00064 if (*dll == '\0') break;
00065 #if defined(WINCE)
00066 p = GetProcAddress(lib, MB_TO_WIDE(dll));
00067 #else
00068 p = GetProcAddress(lib, dll);
00069 #endif
00070 if (p == NULL) return false;
00071 *proc++ = (Function)p;
00072 }
00073 dll++;
00074 }
00075 return true;
00076 }
00077
00078 void ShowOSErrorBox(const char *buf, bool system)
00079 {
00080 MyShowCursor(true);
00081 MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP);
00082 }
00083
00084 void OSOpenBrowser(const char *url)
00085 {
00086 ShellExecute(GetActiveWindow(), _T("open"), MB_TO_WIDE(url), NULL, NULL, SW_SHOWNORMAL);
00087 }
00088
00089
00090
00091
00092
00093 struct DIR {
00094 HANDLE hFind;
00095
00096
00097
00098 dirent ent;
00099 WIN32_FIND_DATA fd;
00100
00101
00102
00103 bool at_first_entry;
00104 };
00105
00106
00107
00108
00109
00110
00111 static DIR _global_dir;
00112 static LONG _global_dir_is_in_use = false;
00113
00114 static inline DIR *dir_calloc()
00115 {
00116 DIR *d;
00117
00118 if (InterlockedExchange(&_global_dir_is_in_use, true) == (LONG)true) {
00119 d = CallocT<DIR>(1);
00120 } else {
00121 d = &_global_dir;
00122 memset(d, 0, sizeof(*d));
00123 }
00124 return d;
00125 }
00126
00127 static inline void dir_free(DIR *d)
00128 {
00129 if (d == &_global_dir) {
00130 _global_dir_is_in_use = (LONG)false;
00131 } else {
00132 free(d);
00133 }
00134 }
00135
00136 DIR *opendir(const TCHAR *path)
00137 {
00138 DIR *d;
00139 UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);
00140 DWORD fa = GetFileAttributes(path);
00141
00142 if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) {
00143 d = dir_calloc();
00144 if (d != NULL) {
00145 TCHAR search_path[MAX_PATH];
00146 bool slash = path[_tcslen(path) - 1] == '\\';
00147
00148
00149
00150 _sntprintf(search_path, lengthof(search_path), _T("%s%s*"), path, slash ? _T("") : _T("\\"));
00151 *lastof(search_path) = '\0';
00152 d->hFind = FindFirstFile(search_path, &d->fd);
00153
00154 if (d->hFind != INVALID_HANDLE_VALUE ||
00155 GetLastError() == ERROR_NO_MORE_FILES) {
00156 d->ent.dir = d;
00157 d->at_first_entry = true;
00158 } else {
00159 dir_free(d);
00160 d = NULL;
00161 }
00162 } else {
00163 errno = ENOMEM;
00164 }
00165 } else {
00166
00167 d = NULL;
00168 errno = ENOENT;
00169 }
00170
00171 SetErrorMode(sem);
00172 return d;
00173 }
00174
00175 struct dirent *readdir(DIR *d)
00176 {
00177 DWORD prev_err = GetLastError();
00178
00179 if (d->at_first_entry) {
00180
00181 if (d->hFind == INVALID_HANDLE_VALUE) return NULL;
00182 d->at_first_entry = false;
00183 } else if (!FindNextFile(d->hFind, &d->fd)) {
00184 if (GetLastError() == ERROR_NO_MORE_FILES) SetLastError(prev_err);
00185 return NULL;
00186 }
00187
00188
00189
00190 d->ent.d_name = d->fd.cFileName;
00191 return &d->ent;
00192 }
00193
00194 int closedir(DIR *d)
00195 {
00196 FindClose(d->hFind);
00197 dir_free(d);
00198 return 0;
00199 }
00200
00201 bool FiosIsRoot(const char *file)
00202 {
00203 return file[3] == '\0';
00204 }
00205
00206 void FiosGetDrives()
00207 {
00208 #if defined(WINCE)
00209
00210 FiosItem *fios = _fios_items.Append();
00211 fios->type = FIOS_TYPE_DRIVE;
00212 fios->mtime = 0;
00213 snprintf(fios->name, lengthof(fios->name), PATHSEP "");
00214 strecpy(fios->title, fios->name, lastof(fios->title));
00215 #else
00216 TCHAR drives[256];
00217 const TCHAR *s;
00218
00219 GetLogicalDriveStrings(lengthof(drives), drives);
00220 for (s = drives; *s != '\0';) {
00221 FiosItem *fios = _fios_items.Append();
00222 fios->type = FIOS_TYPE_DRIVE;
00223 fios->mtime = 0;
00224 snprintf(fios->name, lengthof(fios->name), "%c:", s[0] & 0xFF);
00225 strecpy(fios->title, fios->name, lastof(fios->title));
00226 while (*s++ != '\0') { }
00227 }
00228 #endif
00229 }
00230
00231 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
00232 {
00233
00234 static const int64 posix_epoch_hns = 0x019DB1DED53E8000LL;
00235 const WIN32_FIND_DATA *fd = &ent->dir->fd;
00236
00237 sb->st_size = ((uint64) fd->nFileSizeHigh << 32) + fd->nFileSizeLow;
00238
00239
00240
00241
00242
00243 sb->st_mtime = (time_t)((*(const uint64*)&fd->ftLastWriteTime - posix_epoch_hns) / 1E7);
00244 sb->st_mode = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG;
00245
00246 return true;
00247 }
00248
00249 bool FiosIsHiddenFile(const struct dirent *ent)
00250 {
00251 return (ent->dir->fd.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != 0;
00252 }
00253
00254 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
00255 {
00256 UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);
00257 bool retval = false;
00258 TCHAR root[4];
00259 DWORD spc, bps, nfc, tnc;
00260
00261 _sntprintf(root, lengthof(root), _T("%c:") _T(PATHSEP), path[0]);
00262 if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
00263 *tot = ((spc * bps) * (uint64)nfc);
00264 retval = true;
00265 }
00266
00267 SetErrorMode(sem);
00268 return retval;
00269 }
00270
00271 static int ParseCommandLine(char *line, char **argv, int max_argc)
00272 {
00273 int n = 0;
00274
00275 do {
00276
00277 while (*line == ' ' || *line == '\t') line++;
00278
00279
00280 if (*line == '\0') break;
00281
00282
00283 if (*line == '"') {
00284 argv[n++] = ++line;
00285 while (*line != '"') {
00286 if (*line == '\0') return n;
00287 line++;
00288 }
00289 } else {
00290 argv[n++] = line;
00291 while (*line != ' ' && *line != '\t') {
00292 if (*line == '\0') return n;
00293 line++;
00294 }
00295 }
00296 *line++ = '\0';
00297 } while (n != max_argc);
00298
00299 return n;
00300 }
00301
00302 void CreateConsole()
00303 {
00304 #if defined(WINCE)
00305
00306 #else
00307 HANDLE hand;
00308 CONSOLE_SCREEN_BUFFER_INFO coninfo;
00309
00310 if (_has_console) return;
00311 _has_console = true;
00312
00313 AllocConsole();
00314
00315 hand = GetStdHandle(STD_OUTPUT_HANDLE);
00316 GetConsoleScreenBufferInfo(hand, &coninfo);
00317 coninfo.dwSize.Y = 500;
00318 SetConsoleScreenBufferSize(hand, coninfo.dwSize);
00319
00320
00321 #if !defined(__CYGWIN__)
00322
00323
00324 int fd = _open_osfhandle((intptr_t)hand, _O_TEXT);
00325 if (fd == -1) {
00326
00327 FreeConsole();
00328 _has_console = false;
00329 _close(fd);
00330 CloseHandle(hand);
00331
00332 ShowInfo("Unable to open an output handle to the console. Check known-bugs.txt for details.");
00333 return;
00334 }
00335
00336 *stdout = *_fdopen(fd, "w");
00337 *stdin = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT), "r" );
00338 *stderr = *_fdopen(_open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT), "w" );
00339 #else
00340
00341 *stdout = *fdopen(1, "w" );
00342 *stdin = *fdopen(0, "r" );
00343 *stderr = *fdopen(2, "w" );
00344 #endif
00345
00346 setvbuf(stdin, NULL, _IONBF, 0);
00347 setvbuf(stdout, NULL, _IONBF, 0);
00348 setvbuf(stderr, NULL, _IONBF, 0);
00349 #endif
00350 }
00351
00353 static const char *_help_msg;
00354
00356 static INT_PTR CALLBACK HelpDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
00357 {
00358 switch (msg) {
00359 case WM_INITDIALOG: {
00360 char help_msg[8192];
00361 const char *p = _help_msg;
00362 char *q = help_msg;
00363 while (q != lastof(help_msg) && *p != '\0') {
00364 if (*p == '\n') {
00365 *q++ = '\r';
00366 if (q == lastof(help_msg)) {
00367 q[-1] = '\0';
00368 break;
00369 }
00370 }
00371 *q++ = *p++;
00372 }
00373 *q = '\0';
00374 #if defined(UNICODE)
00375
00376
00377 wchar_t help_msgW[8192];
00378 #endif
00379 SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(help_msg, help_msgW, lengthof(help_msgW)));
00380 SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
00381 } return TRUE;
00382
00383 case WM_COMMAND:
00384 if (wParam == 12) ExitProcess(0);
00385 return TRUE;
00386 case WM_CLOSE:
00387 ExitProcess(0);
00388 }
00389
00390 return FALSE;
00391 }
00392
00393 void ShowInfo(const char *str)
00394 {
00395 if (_has_console) {
00396 fprintf(stderr, "%s\n", str);
00397 } else {
00398 bool old;
00399 ReleaseCapture();
00400 _left_button_clicked = _left_button_down = false;
00401
00402 old = MyShowCursor(true);
00403 if (strlen(str) > 2048) {
00404
00405
00406
00407 _help_msg = str;
00408 DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(101), NULL, HelpDialogFunc);
00409 } else {
00410 #if defined(UNICODE)
00411
00412
00413 wchar_t help_msgW[8192];
00414 #endif
00415 MessageBox(GetActiveWindow(), MB_TO_WIDE_BUFFER(str, help_msgW, lengthof(help_msgW)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OK);
00416 }
00417 MyShowCursor(old);
00418 }
00419 }
00420
00421 #if defined(WINCE)
00422 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
00423 #else
00424 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
00425 #endif
00426 {
00427 int argc;
00428 char *argv[64];
00429 char *cmdline;
00430
00431 #if !defined(UNICODE)
00432 _codepage = GetACP();
00433 #endif
00434
00435 CrashLog::InitialiseCrashLog();
00436
00437 #if defined(UNICODE)
00438
00439 #if !defined(WINCE)
00440
00441 if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again.");
00442 #endif
00443
00444
00445
00446
00447 char cmdlinebuf[MAX_PATH];
00448 #endif
00449
00450 cmdline = WIDE_TO_MB_BUFFER(GetCommandLine(), cmdlinebuf, lengthof(cmdlinebuf));
00451
00452 #if defined(_DEBUG)
00453 CreateConsole();
00454 #endif
00455
00456 #if !defined(WINCE)
00457 _set_error_mode(_OUT_TO_MSGBOX);
00458 #endif
00459
00460
00461 SetRandomSeed(GetTickCount());
00462
00463 argc = ParseCommandLine(cmdline, argv, lengthof(argv));
00464
00465 ttd_main(argc, argv);
00466 return 0;
00467 }
00468
00469 #if defined(WINCE)
00470 void GetCurrentDirectoryW(int length, wchar_t *path)
00471 {
00472
00473 GetModuleFileName(NULL, path, length);
00474
00475
00476 wchar_t *pDest = wcsrchr(path, '\\');
00477 if (pDest != NULL) {
00478 int result = pDest - path + 1;
00479 path[result] = '\0';
00480 }
00481 }
00482 #endif
00483
00484 char *getcwd(char *buf, size_t size)
00485 {
00486 #if defined(WINCE)
00487 TCHAR path[MAX_PATH];
00488 GetModuleFileName(NULL, path, MAX_PATH);
00489 convert_from_fs(path, buf, size);
00490
00491 char *p = strrchr(buf, '\\');
00492 if (p != NULL) *p = '\0';
00493 #elif defined(UNICODE)
00494 TCHAR path[MAX_PATH];
00495 GetCurrentDirectory(MAX_PATH - 1, path);
00496 convert_from_fs(path, buf, size);
00497 #else
00498 GetCurrentDirectory(size, buf);
00499 #endif
00500 return buf;
00501 }
00502
00503
00504 void DetermineBasePaths(const char *exe)
00505 {
00506 char tmp[MAX_PATH];
00507 TCHAR path[MAX_PATH];
00508 #ifdef WITH_PERSONAL_DIR
00509 if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path))) {
00510 strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
00511 AppendPathSeparator(tmp, MAX_PATH);
00512 ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
00513 AppendPathSeparator(tmp, MAX_PATH);
00514 _searchpaths[SP_PERSONAL_DIR] = strdup(tmp);
00515 } else {
00516 _searchpaths[SP_PERSONAL_DIR] = NULL;
00517 }
00518
00519 if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path))) {
00520 strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
00521 AppendPathSeparator(tmp, MAX_PATH);
00522 ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
00523 AppendPathSeparator(tmp, MAX_PATH);
00524 _searchpaths[SP_SHARED_DIR] = strdup(tmp);
00525 } else {
00526 _searchpaths[SP_SHARED_DIR] = NULL;
00527 }
00528 #else
00529 _searchpaths[SP_PERSONAL_DIR] = NULL;
00530 _searchpaths[SP_SHARED_DIR] = NULL;
00531 #endif
00532
00533
00534 getcwd(tmp, lengthof(tmp));
00535 AppendPathSeparator(tmp, MAX_PATH);
00536 _searchpaths[SP_WORKING_DIR] = strdup(tmp);
00537
00538 if (!GetModuleFileName(NULL, path, lengthof(path))) {
00539 DEBUG(misc, 0, "GetModuleFileName failed (%lu)\n", GetLastError());
00540 _searchpaths[SP_BINARY_DIR] = NULL;
00541 } else {
00542 TCHAR exec_dir[MAX_PATH];
00543 _tcsncpy(path, MB_TO_WIDE_BUFFER(exe, path, lengthof(path)), lengthof(path));
00544 if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) {
00545 DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError());
00546 _searchpaths[SP_BINARY_DIR] = NULL;
00547 } else {
00548 strecpy(tmp, WIDE_TO_MB_BUFFER(exec_dir, tmp, lengthof(tmp)), lastof(tmp));
00549 char *s = strrchr(tmp, PATHSEPCHAR);
00550 *(s + 1) = '\0';
00551 _searchpaths[SP_BINARY_DIR] = strdup(tmp);
00552 }
00553 }
00554
00555 _searchpaths[SP_INSTALLATION_DIR] = NULL;
00556 _searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
00557 }
00558
00559
00560 bool GetClipboardContents(char *buffer, size_t buff_len)
00561 {
00562 HGLOBAL cbuf;
00563 const char *ptr;
00564
00565 if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
00566 OpenClipboard(NULL);
00567 cbuf = GetClipboardData(CF_UNICODETEXT);
00568
00569 ptr = (const char*)GlobalLock(cbuf);
00570 const char *ret = convert_from_fs((const wchar_t*)ptr, buffer, buff_len);
00571 GlobalUnlock(cbuf);
00572 CloseClipboard();
00573
00574 if (*ret == '\0') return false;
00575 #if !defined(UNICODE)
00576 } else if (IsClipboardFormatAvailable(CF_TEXT)) {
00577 OpenClipboard(NULL);
00578 cbuf = GetClipboardData(CF_TEXT);
00579
00580 ptr = (const char*)GlobalLock(cbuf);
00581 ttd_strlcpy(buffer, FS2OTTD(ptr), buff_len);
00582
00583 GlobalUnlock(cbuf);
00584 CloseClipboard();
00585 #endif
00586 } else {
00587 return false;
00588 }
00589
00590 return true;
00591 }
00592
00593
00594 void CSleep(int milliseconds)
00595 {
00596 Sleep(milliseconds);
00597 }
00598
00599
00613 const char *FS2OTTD(const TCHAR *name)
00614 {
00615 static char utf8_buf[512];
00616 #if defined(UNICODE)
00617 return convert_from_fs(name, utf8_buf, lengthof(utf8_buf));
00618 #else
00619 char *s = utf8_buf;
00620
00621 for (; *name != '\0'; name++) {
00622 wchar_t w;
00623 int len = MultiByteToWideChar(_codepage, 0, name, 1, &w, 1);
00624 if (len != 1) {
00625 DEBUG(misc, 0, "[utf8] M2W error converting '%c'. Errno %lu", *name, GetLastError());
00626 continue;
00627 }
00628
00629 if (s + Utf8CharLen(w) >= lastof(utf8_buf)) break;
00630 s += Utf8Encode(s, w);
00631 }
00632
00633 *s = '\0';
00634 return utf8_buf;
00635 #endif
00636 }
00637
00651 const TCHAR *OTTD2FS(const char *name)
00652 {
00653 static TCHAR system_buf[512];
00654 #if defined(UNICODE)
00655 return convert_to_fs(name, system_buf, lengthof(system_buf));
00656 #else
00657 char *s = system_buf;
00658
00659 for (WChar c; (c = Utf8Consume(&name)) != '\0';) {
00660 if (s >= lastof(system_buf)) break;
00661
00662 char mb;
00663 int len = WideCharToMultiByte(_codepage, 0, (wchar_t*)&c, 1, &mb, 1, NULL, NULL);
00664 if (len != 1) {
00665 DEBUG(misc, 0, "[utf8] W2M error converting '0x%X'. Errno %lu", c, GetLastError());
00666 continue;
00667 }
00668
00669 *s++ = mb;
00670 }
00671
00672 *s = '\0';
00673 return system_buf;
00674 #endif
00675 }
00676
00677
00686 char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
00687 {
00688 int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, NULL, NULL);
00689 if (len == 0) {
00690 DEBUG(misc, 0, "[utf8] W2M error converting wide-string. Errno %lu", GetLastError());
00691 utf8_buf[0] = '\0';
00692 }
00693
00694 return utf8_buf;
00695 }
00696
00697
00707 wchar_t *convert_to_fs(const char *name, wchar_t *utf16_buf, size_t buflen)
00708 {
00709 int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, utf16_buf, (int)buflen);
00710 if (len == 0) {
00711 DEBUG(misc, 0, "[utf8] M2W error converting '%s'. Errno %lu", name, GetLastError());
00712 utf16_buf[0] = '\0';
00713 }
00714
00715 return utf16_buf;
00716 }
00717
00724 HRESULT OTTDSHGetFolderPath(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
00725 {
00726 static HRESULT (WINAPI *SHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR) = NULL;
00727 static bool first_time = true;
00728
00729
00730 if (first_time) {
00731 #if defined(UNICODE)
00732 # define W(x) x "W"
00733 #else
00734 # define W(x) x "A"
00735 #endif
00736
00737 if (!LoadLibraryList((Function*)&SHGetFolderPath, "shell32.dll\0" W("SHGetFolderPath") "\0\0")) {
00738 if (!LoadLibraryList((Function*)&SHGetFolderPath, "SHFolder.dll\0" W("SHGetFolderPath") "\0\0")) {
00739 DEBUG(misc, 0, "Unable to load " W("SHGetFolderPath") "from either shell32.dll or SHFolder.dll");
00740 }
00741 }
00742 #undef W
00743 first_time = false;
00744 }
00745
00746 if (SHGetFolderPath != NULL) return SHGetFolderPath(hwnd, csidl, hToken, dwFlags, pszPath);
00747
00748
00749
00750
00751
00752
00753
00754
00755 {
00756 DWORD ret;
00757 switch (csidl) {
00758 case CSIDL_FONTS:
00759 ret = GetEnvironmentVariable(_T("WINDIR"), pszPath, MAX_PATH);
00760 if (ret == 0) break;
00761 _tcsncat(pszPath, _T("\\Fonts"), MAX_PATH);
00762
00763 return (HRESULT)0;
00764
00765 case CSIDL_PERSONAL:
00766 case CSIDL_COMMON_DOCUMENTS: {
00767 HKEY key;
00768 if (RegOpenKeyEx(csidl == CSIDL_PERSONAL ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, REGSTR_PATH_SPECIAL_FOLDERS, 0, KEY_READ, &key) != ERROR_SUCCESS) break;
00769 DWORD len = MAX_PATH;
00770 ret = RegQueryValueEx(key, csidl == CSIDL_PERSONAL ? _T("Personal") : _T("Common Documents"), NULL, NULL, (LPBYTE)pszPath, &len);
00771 RegCloseKey(key);
00772 if (ret == ERROR_SUCCESS) return (HRESULT)0;
00773 break;
00774 }
00775
00776
00777 }
00778 }
00779
00780 return E_INVALIDARG;
00781 }
00782
00784 const char *GetCurrentLocale(const char *)
00785 {
00786 char lang[9], country[9];
00787 if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lang, lengthof(lang)) == 0 ||
00788 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, country, lengthof(country)) == 0) {
00789
00790 return NULL;
00791 }
00792
00793 static char retbuf[6] = {lang[0], lang[1], '_', country[0], country[1], 0};
00794 return retbuf;
00795 }
00796
00797 uint GetCPUCoreCount()
00798 {
00799 SYSTEM_INFO info;
00800
00801 GetSystemInfo(&info);
00802 return info.dwNumberOfProcessors;
00803 }