00001 #ifndef PORTABLE_IMPLEMENTATION_FILE
00002 #define PORTABLE_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "build_configuration.h"
00020 #include "convert_utf.h"
00021 #include "function.h"
00022 #include "mutex.h"
00023 #include "portable.h"
00024 #include "set.cpp"
00025 #include "version_record.h"
00026
00027 #include <errno.h>
00028 #include <stdlib.h>
00029
00030 #ifdef __UNIX__
00031 #include <limits.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <sys/poll.h>
00035 #include <sys/times.h>
00036 #include <sys/utsname.h>
00037 #include <sys/wait.h>
00038 #include <time.h>
00039 #include <unistd.h>
00040 #endif
00041 #ifdef __XWINDOWS__
00042
00043 #endif
00044 #ifdef __WIN32__
00045 #include <mmsystem.h>
00046 #include <process.h>
00047 #include <shellapi.h>
00048 #include <shlobj.h>
00049 #endif
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifdef JUMP_TIME_49_DAYS
00078 #undef DEBUG_UPTIME
00079 #define DEBUG_UPTIME
00080 #endif
00081 #ifdef JUMP_TIME_497_DAYS
00082 #undef DEBUG_UPTIME
00083 #define DEBUG_UPTIME
00084 #endif
00085
00086 #ifdef JUMP_TIME_497_DAYS
00087 #ifdef JUMP_TIME_49_DAYS
00088 #error One cannot use both 497 day and 49 day bug inducers
00089 #endif
00090 #endif
00091 #ifdef JUMP_TIME_49_DAYS
00092 #ifdef JUMP_TIME_497_DAYS
00093 #error One cannot use both 49 day and 497 day bug inducers
00094 #endif
00095 #endif
00096
00097 mutex BASIS_EXTERN &__uptime_synchronizer();
00098
00099 mutex BASIS_EXTERN &__process_synchronizer();
00100
00101 #ifdef __UNIX__
00102 int_set BASIS_EXTERN &__our_kids();
00103
00104 #endif
00105
00106 const int MAXIMUM_COMMAND_LINE = 32 * KILOBYTE;
00107
00108
00109 #ifdef __UNIX__
00110 const char *UPTIME_REPORT_FILE = "/tmp/uptime_report.log";
00111 #endif
00112 #ifdef __WIN32__
00113 const char *UPTIME_REPORT_FILE = "c:/uptime_report.log";
00114 #endif
00115
00116 #undef LOG
00117 #define LOG(s) STAMPED_EMERGENCY_LOG(program_wide_logger(), s);
00118
00119 #undef static_class_name
00120 #define static_class_name() "portable"
00121
00122 namespace portable {
00123
00124 #define COMPLAIN(to_print) { \
00125 guards::write_to_console((isprintf("basis/portable::%s: ", func) + to_print).s()); \
00126 }
00127
00128 static const double __rollover_point = 2.0 * double(MAXINT);
00129
00130
00131 double rolling_uptime()
00132 {
00133 auto_synchronizer l(__uptime_synchronizer());
00134
00135
00136 static u_int __last_ticks = 0;
00137 static int __rollovers = 0;
00138
00139 u_int ticks_up = system_uptime();
00140
00141
00142 if (ticks_up < __last_ticks) {
00143
00144 __rollovers++;
00145 }
00146 __last_ticks = ticks_up;
00147
00148 double to_return = double(__rollovers) * __rollover_point + double(ticks_up);
00149
00150 #ifdef DEBUG_UPTIME
00151 #ifdef __WIN32__
00152 static FILE *__outfile = fopen(UPTIME_REPORT_FILE, "a+b");
00153 static double old_value = 0;
00154 if (absolute_value(old_value - to_return) > 9.9999) {
00155
00156 fprintf(__outfile, "-> uptime=%.0f\n", to_return);
00157 fflush(__outfile);
00158 old_value = to_return;
00159 if (__rollover_point - to_return <= 40.00001) {
00160 fprintf(__outfile, "---> MAXIMUM UPTIME SOON!\n");
00161 fflush(__outfile);
00162 }
00163 }
00164 #endif
00165 #endif
00166
00167 return to_return;
00168 }
00169
00170 u_int system_uptime()
00171 {
00172 #ifdef __WIN32__
00173 return timeGetTime();
00174 #else
00175 auto_synchronizer l(__uptime_synchronizer());
00176
00177 static clock_t __ctps = sysconf(_SC_CLK_TCK);
00178 static const double __multiplier = 1000.0 / double(__ctps);
00179
00180
00181 #ifdef DEBUG_UPTIME
00182 static FILE *__outfile = fopen(UPTIME_REPORT_FILE, "wb");
00183 if (__multiplier - u_int(__multiplier) > 0.000001) {
00184 fprintf(__outfile, "uptime multiplier is "
00185 "non-integral (%f)!\n", __multiplier);
00186 fflush(__outfile);
00187 }
00188 #endif
00189
00190
00191 tms uptime;
00192 u_int real_ticks = times(&uptime);
00193
00194 #ifdef JUMP_TIME_497_DAYS
00195 static u_int old_value_497 = 0;
00196 bool report_497 = (absolute_value(real_ticks - old_value_497) > 99);
00197 if (report_497) {
00198 old_value_497 = real_ticks;
00199 fprintf(__outfile, "pre kludge497 tix=%u\n", real_ticks);
00200 fflush(__outfile);
00201 }
00202 real_ticks += u_int(49.0 * double(DAY_ms) + 17.0 * double(HOUR_ms));
00203 if (report_497) {
00204 fprintf(__outfile, "post kludge497 tix=%u\n", real_ticks);
00205 fflush(__outfile);
00206 }
00207 #endif
00208
00209
00210 double ticks_up = (double)real_ticks;
00211 ticks_up = ticks_up * __multiplier;
00212
00213 #ifdef JUMP_TIME_497_DAYS
00214 #ifndef ENABLE_ROLLOVER_BUG
00215
00216
00217
00218
00219
00220
00221
00222
00223 ticks_up += 25.0 * MINUTE_ms;
00224 #endif
00225 #endif
00226
00227 #ifdef JUMP_TIME_49_DAYS
00228 static u_int old_value_49 = 0;
00229 bool report_49 = (absolute_value(u_int(ticks_up) - old_value_49) > 999);
00230 if (report_49) {
00231 old_value_49 = u_int(ticks_up);
00232 fprintf(__outfile, "pre kludge49 up=%f\n", ticks_up);
00233 fflush(__outfile);
00234 }
00235 ticks_up += 49.0 * double(DAY_ms) + 17.0 * double(HOUR_ms);
00236 if (report_49) {
00237 fprintf(__outfile, "post kludge49 up=%f\n", ticks_up);
00238 fflush(__outfile);
00239 }
00240 #endif
00241
00242 #ifndef ENABLE_ROLLOVER_BUG
00243
00244
00245
00246
00247
00248
00249 u_int divided = u_int(ticks_up / __rollover_point);
00250 double to_return = ticks_up - (double(divided) * __rollover_point);
00251 #else
00252
00253
00254
00255
00256
00257
00258 double to_return = ticks_up;
00259 #endif
00260
00261 #ifdef DEBUG_UPTIME
00262 static u_int old_value = 0;
00263 int to_print = int(u_int(to_return));
00264 if (absolute_value(int(old_value) - to_print) > 9) {
00265
00266 fprintf(__outfile, "-> uptime=%u\n", to_print);
00267 fflush(__outfile);
00268 old_value = u_int(to_print);
00269 if (__rollover_point - to_return <= 40.00001) {
00270 fprintf(__outfile, "---> MAXIMUM UPTIME SOON!\n");
00271 fflush(__outfile);
00272 }
00273 }
00274 #endif
00275
00276 return u_int(to_return);
00277 #endif
00278 }
00279
00280 void sleep_ms(u_int msec)
00281 {
00282 #ifdef __UNIX__
00283 usleep(msec * 1000);
00284 #endif
00285 #ifdef __WIN32__
00286 Sleep(msec);
00287 #endif
00288 }
00289
00290 istring null_device()
00291 {
00292 #ifdef __WIN32__
00293 return "null:";
00294 #else
00295 return "/dev/null";
00296 #endif
00297 }
00298
00299 #ifdef __WIN32__
00300 bool event_poll(MSG &message)
00301 {
00302 message.hwnd = 0;
00303 message.message = 0;
00304 message.wParam = 0;
00305 message.lParam = 0;
00306 if (!PeekMessage(&message, NIL, 0, 0, PM_REMOVE))
00307 return false;
00308 TranslateMessage(&message);
00309 DispatchMessage(&message);
00310 return true;
00311 }
00312 #endif
00313
00314
00315 #ifndef EMBEDDED_BUILD
00316 #define COMPLAIN_QUERY(to_print) { \
00317 unlink(tmpfile.s()); \
00318 COMPLAIN(to_print); \
00319 }
00320 #else
00321 #define COMPLAIN_QUERY(to_print) { \
00322 COMPLAIN(to_print); \
00323 }
00324 #endif
00325
00326 #ifdef __UNIX__
00327 istring get_cmdline_from_proc()
00328 {
00329 FUNCDEF("get_cmdline_from_proc");
00330 isprintf cmds_filename("/proc/%d/cmdline", process_id());
00331 FILE *cmds_file = fopen(cmds_filename.s(), "r");
00332 if (!cmds_file) {
00333 COMPLAIN("failed to open our process's command line file.\n");
00334 return "unknown";
00335 }
00336 size_t size = 2000;
00337 char *buff = new char[size + 1];
00338 ssize_t chars_read = getline(&buff, &size, cmds_file);
00339
00340 fclose(cmds_file);
00341 if (!chars_read || negative(chars_read)) {
00342 COMPLAIN("failed to get any characters from our process's cmdline file.\n");
00343 return "unknown";
00344 }
00345 istring buffer = buff;
00346 delete [] buff;
00347
00348 for (int i = buffer.length() - 1; i >= 0; i--) {
00349 if (buffer[i] == '"') buffer.zap(i, i);
00350 }
00351 return buffer;
00352 }
00353
00354
00355 istring query_for_process_info()
00356 {
00357 FUNCDEF("query_for_process_info");
00358 istring to_return = "unknown";
00359
00360
00361 chaos rando;
00362 isprintf tmpfile("/tmp/proc_name_check_%d_%d.txt", process_id(),
00363 rando.inclusive(0, 128000));
00364 isprintf cmd("ps h --format \"%%a\" %d >%s", process_id(), tmpfile.s());
00365
00366 int sysret = system(cmd.s());
00367 if (negative(sysret)) {
00368 COMPLAIN_QUERY("failed to run ps command to get process info");
00369 return to_return;
00370 }
00371
00372 FILE *output = fopen(tmpfile.s(), "r");
00373 if (!output) {
00374 COMPLAIN_QUERY("failed to open the ps output file");
00375 return to_return;
00376 }
00377
00378 char buff[MAXIMUM_COMMAND_LINE];
00379 size_t size_read = fread(buff, 1, MAXIMUM_COMMAND_LINE, output);
00380 if (size_read > 0) {
00381
00382 while (size_read > 0) {
00383 const char to_check = buff[size_read - 1];
00384 if ( !to_check || (to_check == '\r') || (to_check == '\n')
00385 || (to_check == '\t') )
00386 size_read--;
00387 else break;
00388 }
00389 to_return.reset(istring::UNTERMINATED, buff, size_read);
00390 } else {
00391
00392 COMPLAIN_QUERY("could not read output of process list");
00393 }
00394 unlink(tmpfile.s());
00395 return to_return;
00396 }
00397 #endif
00398
00399
00400 #ifndef EMBEDDED_BUILD
00401 #define SET_BOGUS_NAME(error) { \
00402 COMPLAIN(error); \
00403 if (output) { \
00404 fclose(output); \
00405 unlink(tmpfile.s()); \
00406 } \
00407 istring home_dir = env_string("HOME"); \
00408 to_return = home_dir + "/failed_to_determine.exe"; \
00409 }
00410 #else
00411 #define SET_BOGUS_NAME(error) { \
00412 COMPLAIN(error); \
00413 to_return = "unknown"; \
00414 }
00415 #endif
00416
00417 istring application_name()
00418 {
00419 FUNCDEF("application_name");
00420 istring to_return;
00421 #ifdef __UNIX__
00422 to_return = get_cmdline_from_proc();
00423 #elif defined(__WIN32__)
00424 flexichar low_buff[MAX_PATH + 1];
00425 GetModuleFileName(NIL, low_buff, MAX_PATH - 1);
00426 istring buff = from_unicode_temp(low_buff);
00427 buff.to_lower();
00428 to_return = buff;
00429 #elif defined(EMBEDDED_BUILD)
00430 SET_BOGUS_NAME("embedded_exe");
00431 #else
00432 #pragma error("hmmm: no means of finding app name is implemented.")
00433 SET_BOGUS_NAME("not_implemented_for_this_OS");
00434 #endif
00435 return to_return;
00436 }
00437
00438 istring module_name(const void *module_handle)
00439 {
00440 #ifdef __UNIX__
00441
00442 if (module_handle) {}
00443 return application_name();
00444 #elif defined(__WIN32__)
00445 flexichar low_buff[MAX_PATH + 1];
00446 GetModuleFileName((HMODULE)module_handle, low_buff, MAX_PATH - 1);
00447 istring buff = from_unicode_temp(low_buff);
00448 buff.to_lower();
00449 return buff;
00450 #else
00451 #pragma message("module_name unknown for this operating system.")
00452 return application_name();
00453 #endif
00454 }
00455
00456 u_int system_error()
00457 {
00458 #if defined(__UNIX__)
00459 return errno;
00460 #elif defined(__WIN32__)
00461 return GetLastError();
00462 #else
00463 #pragma error("hmmm: no code for error number for this operating system")
00464 return 0;
00465 #endif
00466 }
00467
00468 istring system_error_text(u_int to_name)
00469 {
00470 #if defined(__UNIX__)
00471 return strerror(to_name);
00472 #elif defined(__WIN32__)
00473 char error_text[1000];
00474 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NIL, to_name,
00475 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)error_text,
00476 sizeof(error_text) - 1, NIL);
00477 istring to_return = error_text;
00478
00479 while ( (to_return[to_return.end()] == '\r')
00480 || (to_return[to_return.end()] == '\n') )
00481 to_return.zap(to_return.end(), to_return.end());
00482 return to_return;
00483 #else
00484 #pragma error("hmmm: no code for error text for this operating system")
00485 return "";
00486 #endif
00487 }
00488
00489 #ifdef __WIN32__
00490
00491 bool is_address_valid(const void *address, int size_expected, bool writable)
00492 {
00493 return address && !IsBadReadPtr(address, size_expected)
00494 && !(writable && IsBadWritePtr((void *)address, size_expected));
00495 }
00496
00497 #endif // win32
00498
00499 version get_OS_version()
00500 {
00501 version to_return;
00502 #ifdef __UNIX__
00503 utsname kernel_parms;
00504 uname(&kernel_parms);
00505 to_return = version(kernel_parms.release);
00506 #elif defined(__WIN32__)
00507 OSVERSIONINFO info;
00508 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00509 ::GetVersionEx(&info);
00510 to_return = version(isprintf("%u.%u.%u.%u", u_short(info.dwMajorVersion),
00511 u_short(info.dwMinorVersion), u_short(info.dwPlatformId),
00512 u_short(info.dwBuildNumber)));
00513 #elif defined(EMBEDDED_BUILD)
00514
00515 #else
00516 #pragma error("hmmm: need version info for this OS!")
00517 #endif
00518 return to_return;
00519 }
00520
00521
00522 #if defined(__UNIX__) || defined(__WIN32__)
00523 u_int process_id() { return getpid(); }
00524 #else
00525 #pragma error("hmmm: need process id implementation for this OS!")
00526 u_int process_id() { return 0; }
00527 #endif
00528
00529 istring current_directory()
00530 {
00531 istring to_return;
00532 #ifdef __UNIX__
00533 char buff[PATH_MAX];
00534 getcwd(buff, PATH_MAX - 1);
00535 to_return = buff;
00536 #elif defined(__WIN32__)
00537 flexichar low_buff[MAX_PATH + 1];
00538 GetCurrentDirectory(MAX_PATH, low_buff);
00539 to_return = from_unicode_temp(low_buff);
00540 #else
00541 #pragma error("hmmm: need support for current directory on this OS.")
00542 to_return = ".";
00543 #endif
00544 return to_return;
00545 }
00546
00547 istring env_string(const istring &variable_name)
00548 {
00549 #ifdef __WIN32__
00550 char *value = getenv(variable_name.upper().observe());
00551
00552 #else
00553 char *value = getenv(variable_name.observe());
00554
00555 #endif
00556 istring to_return;
00557 if (value)
00558 to_return = istring(value);
00559 return to_return;
00560 }
00561
00562 bool set_environ(const istring &variable_name, const istring &value)
00563 {
00564 int ret = 0;
00565 #ifdef __WIN32__
00566 ret = putenv((variable_name + "=" + value).s());
00567 #else
00568 ret = setenv(variable_name.s(), value.s(), true);
00569 #endif
00570 return !ret;
00571 }
00572
00573 timeval fill_timeval_ms(int duration)
00574 {
00575 timeval time_out;
00576 if (!duration) {
00577
00578 time_out.tv_sec = 0;
00579 time_out.tv_usec = 0;
00580 #ifdef DEBUG_PORTABLE
00581
00582 #endif
00583 } else {
00584
00585 time_out.tv_sec = duration / 1000;
00586
00587 duration -= time_out.tv_sec * 1000;
00588
00589 time_out.tv_usec = duration * 1000;
00590
00591 #ifdef DEBUG_PORTABLE
00592
00593
00594 #endif
00595 }
00596 return time_out;
00597 }
00598
00599
00600 char_star_array break_line(istring &app, const istring ¶meters)
00601 {
00602 char_star_array to_return;
00603 int_array posns;
00604 int num = 0;
00605
00606 for (int j = 0; j < parameters.length(); j++) {
00607 if (parameters[j] == ' ') {
00608 num++;
00609 posns += j;
00610 }
00611 }
00612
00613 to_return += new char[app.length() + 1];
00614 app.stuff(to_return[0], app.length());
00615 int last_posn = 0;
00616
00617 for (int i = 0; i < num; i++) {
00618 int len = posns[i] - last_posn;
00619 to_return += new char[len + 1];
00620 parameters.substring(last_posn, posns[i] - 1).stuff(to_return[i + 1], len);
00621 last_posn = posns[i] + 1;
00622 }
00623
00624 if (last_posn < parameters.length() - 1) {
00625 int len = parameters.length() - last_posn;
00626 to_return += new char[len + 1];
00627 parameters.substring(last_posn, parameters.length() - 1)
00628 .stuff(to_return[to_return.last()], len);
00629 }
00630
00631 to_return += NIL;
00632 #ifdef DEBUG_PORTABLE
00633 for (int q = 0; to_return[q]; q++) {
00634 printf("%d: %s\n", q, to_return[q]);
00635 }
00636 #endif
00637
00638
00639 if (app[0] == '"') app.zap(0, 0);
00640 if (app[app.end()] == '"') app.zap(app.end(), app.end());
00641 return to_return;
00642 }
00643
00644 #ifdef __UNIX__
00645
00646 void exiting_child_signal_handler(int sig_num)
00647 {
00648 FUNCDEF("exiting_child_signal_handler");
00649 if (sig_num != SIGCHLD) {
00650
00651 }
00652 auto_synchronizer l(__process_synchronizer());
00653 for (int i = 0; i < __our_kids().length(); i++) {
00654 int status;
00655 pid_t exited = waitpid(__our_kids()[i], &status, WNOHANG);
00656 if ( (exited == -1) || (exited == __our_kids()[i]) ) {
00657
00658
00659
00660 __our_kids().zap(i, i);
00661 i--;
00662 } else if (exited != 0) {
00663
00664 #ifdef DEBUG_PORTABLE
00665 printf("unknown result %d waiting for process %d", exited,
00666 __our_kids()[i]);
00667 #endif
00668 }
00669 }
00670 }
00671 #endif
00672
00673 u_int launch_process(const istring &app_name_in, const istring &command_line,
00674 int flag, u_int &child_id)
00675 {
00676 child_id = 0;
00677 istring app_name = app_name_in;
00678 if (app_name[0] != '"')
00679 app_name.insert(0, "\"");
00680 if (app_name[app_name.end()] != '"')
00681 app_name += "\"";
00682 #ifdef __UNIX__
00683
00684 if (flag & RETURN_IMMEDIATELY) {
00685
00686 pid_t kid_pid = fork();
00687 #ifdef DEBUG_PORTABLE
00688 printf("launch fork returned %d\n", kid_pid);
00689 #endif
00690 if (!kid_pid) {
00691
00692 #ifdef DEBUG_PORTABLE
00693 printf((isprintf("process %d execing ", process_id()) + app_name
00694 + " parms " + command_line + "\n").s());
00695 #endif
00696 char_star_array parms = break_line(app_name, command_line);
00697 execv(app_name.s(), parms.observe());
00698
00699 #ifdef DEBUG_PORTABLE
00700 printf((isprintf("child of fork (pid %d) failed to exec, "
00701 "error is ", process_id()) + system_error_text(system_error())
00702 + "\n").s());
00703 #endif
00704 exit(0);
00705 } else {
00706
00707 if (kid_pid == -1) {
00708
00709 u_int to_return = system_error();
00710 #ifdef DEBUG_PORTABLE
00711 printf((isprintf("parent %d is returning after failing to create, "
00712 "error is ", process_id()) + system_error_text(to_return)
00713 + "\n").s());
00714 #endif
00715 return to_return;
00716 } else {
00717
00718 child_id = kid_pid;
00719 {
00720 auto_synchronizer l(__process_synchronizer());
00721 __our_kids() += kid_pid;
00722 }
00723
00724 signal(SIGCHLD, exiting_child_signal_handler);
00725
00726 #ifdef DEBUG_PORTABLE
00727 printf((isprintf("parent %d is returning after successfully "
00728 "creating %d ", process_id(), kid_pid) + app_name
00729 + " parms " + command_line + "\n").s());
00730 #endif
00731 return 0;
00732 }
00733 }
00734 } else {
00735
00736 return system((app_name + " " + command_line).s());
00737 }
00738 #elif defined(__WIN32__)
00739
00740
00741
00742
00743
00744
00745
00746
00747 PROCESS_INFORMATION process_info;
00748 ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
00749
00750 #ifdef SUPPORT_SHELL_EXECUTE
00751 if (flag & SHELL_EXECUTE) {
00752
00753
00754 int show_cmd = 0;
00755 if (flag & HIDE_APP_WINDOW) {
00756
00757 show_cmd = SW_HIDE;
00758 } else {
00759 show_cmd = SW_SHOWNORMAL;
00760 }
00761
00762 SHELLEXECUTEINFO exec_info;
00763 ZeroMemory(&exec_info, sizeof(SHELLEXECUTEINFO));
00764 exec_info.cbSize = sizeof(SHELLEXECUTEINFO);
00765 exec_info.fMask = SEE_MASK_NOCLOSEPROCESS
00766 | SEE_MASK_FLAG_NO_UI;
00767 exec_info.hwnd = GetDesktopWindow();
00768
00769 to_unicode_persist(temp_verb, "open");
00770
00771 exec_info.lpVerb = temp_verb;
00772 to_unicode_persist(temp_file, app_name);
00773 exec_info.lpFile = temp_file;
00774 to_unicode_persist(temp_parms, command_line);
00775 exec_info.lpParameters = temp_parms;
00776 exec_info.nShow = show_cmd;
00777
00778
00779 BOOL worked = ShellExecuteEx(&exec_info);
00780 if (!worked)
00781 return system_error();
00782
00783 process_info.hProcess = exec_info.hProcess;
00784 process_info.dwProcessId = GetProcessId(exec_info.hProcess);
00785 } else {
00786 #endif //shell exec
00787
00788 STARTUPINFO startup_info;
00789 ZeroMemory(&startup_info, sizeof(STARTUPINFO));
00790 startup_info.cb = sizeof(STARTUPINFO);
00791 int create_flag = 0;
00792 if (flag & HIDE_APP_WINDOW) {
00793
00794
00795
00796
00797
00798 create_flag = CREATE_NO_WINDOW;
00799
00800 }
00801 istring parms = app_name + " " + command_line;
00802 bool success = CreateProcess(NIL, to_unicode_temp(parms), NIL, NIL, false,
00803 create_flag, NIL, NIL, &startup_info, &process_info);
00804 if (!success)
00805 return system_error();
00806
00807
00808 #ifdef SUPPORT_SHELL_EXECUTE
00809 }
00810 #endif //shell exec
00811
00812
00813 child_id = process_info.dwProcessId;
00814 u_long retval = 0;
00815 if (flag & AWAIT_VIA_POLLING) {
00816
00817 while (true) {
00818 MSG msg;
00819 event_poll(msg);
00820
00821 BOOL ret = GetExitCodeProcess(process_info.hProcess, &retval);
00822 if (!ret) {
00823 break;
00824 } else {
00825
00826 if (retval != STILL_ACTIVE)
00827 break;
00828 }
00829 sleep_ms(14);
00830 }
00831 } else if (flag & AWAIT_APP_EXIT) {
00832
00833 WaitForInputIdle(process_info.hProcess, INFINITE);
00834 WaitForSingleObject(process_info.hProcess, INFINITE);
00835 GetExitCodeProcess(process_info.hProcess, &retval);
00836 }
00837
00838 if (process_info.hProcess)
00839 CloseHandle(process_info.hProcess);
00840 if (process_info.hThread)
00841 CloseHandle(process_info.hThread);
00842 return (u_int)retval;
00843 #else
00844 #pragma error("hmmm: launch_process: no implementation for this OS.")
00845 #endif
00846 return 0;
00847 }
00848
00850
00851 #ifdef __UNIX__
00852
00853 char *itoa(int to_convert, char *buffer, int radix)
00854 {
00855
00856
00857 const char *formatter = "%d";
00858 if (radix == 16) formatter = "%x";
00859 isprintf printed(formatter, to_convert);
00860 printed.stuff(buffer, printed.length() + 1);
00861 return buffer;
00862 }
00863
00864 #endif
00865
00866 #ifdef __WIN32__
00867
00868 void show_wait_cursor() { SetCursor(LoadCursor(NULL, IDC_WAIT)); }
00869
00870 void show_normal_cursor() { SetCursor(LoadCursor(NULL, IDC_ARROW)); }
00871
00872 istring rc_string(UINT id, application_instance instance)
00873 {
00874 flexichar temp[MAX_PATH + 1];
00875 int ret = LoadString(instance, id, temp, MAX_PATH);
00876 if (!ret) return istring();
00877 return istring(from_unicode_temp(temp));
00878 }
00879
00880 istring rc_string(u_int id) { return rc_string(id, GET_INSTANCE_HANDLE()); }
00881
00882 bool has_win95_style_shell()
00883 {
00884 u_int os_version = GetVersion();
00885 if (os_version < 0x80000000) {
00886
00887 if (low_byte(low_short(os_version)) >= 4)
00888 return true;
00889 } else {
00890
00891 if (low_byte(low_short(os_version)) >= 4)
00892 return true;
00893 }
00894 return false;
00895 }
00896
00897 known_operating_systems determine_OS()
00898 {
00899 version osver = get_OS_version();
00900 if ( (osver.v_major() == 4) && (osver.v_minor() == 0) ) {
00901 if (osver.v_revision() == VER_PLATFORM_WIN32_WINDOWS) return WIN_95;
00902 if (osver.v_revision() == VER_PLATFORM_WIN32_NT) return WIN_NT;
00903 } else if ( (osver.v_major() == 5) && (osver.v_minor() == 0) ) {
00904 return WIN_2K;
00905 } else if ( (osver.v_major() == 5) && (osver.v_minor() == 1) ) {
00906 return WIN_XP;
00907 }
00908 return UNKNOWN_OS;
00909 }
00910
00911 #endif // win32
00912
00913 }
00914
00915 #undef static_class_name
00916
00917 #endif //PORTABLE_IMPLEMENTATION_FILE
00918