diff --git a/src/platform_win32.cc b/src/platform_win32.cc new file mode 100644 index 00000000000..4fcade8bce8 --- /dev/null +++ b/src/platform_win32.cc @@ -0,0 +1,246 @@ +#include "node.h" +#include "platform.h" + +#include // for MAXPATHLEN +#include // getpagesize +#include + + +namespace node { + +static char buf[MAXPATHLEN + 1]; +static char *process_title = NULL; + + +// Does the about the same as perror(), but for windows api functions +static void _winapi_perror(const char* prefix = NULL) { + DWORD errno = GetLastError(); + char *errmsg; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errmsg, 0, NULL); + + // FormatMessage messages include a newline character + + if (prefix) { + fprintf(stderr, "%s: %s", prefix, errmsg); + } else { + fputs(errmsg, stderr); + } +} + + +char** OS::SetupArgs(int argc, char *argv[]) { + return argv; +} + + +void OS::SetProcessTitle(char *title) { + // We need to convert _title_ to UTF-16 first, because that's what windows uses internally. + // It would be more efficient to use the UTF-16 value that we can obtain from v8, + // but it's not accessible from here. + + // Max title length; according to the specs it should be 64K but in practice it's a little over 30000, + // but who needs titles that long anyway? + const int MAX_TITLE_LENGTH = 30001; + + int length; + WCHAR *title_w; + + // Find out how big the buffer for the wide-char title must be + length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); + if (!length) { + _winapi_perror("MultiByteToWideChar"); + return; + } + + // Convert to wide-char string + title_w = new WCHAR[length]; + length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length); + if (!length) { + _winapi_perror("MultiByteToWideChar"); + delete title_w; + return; + }; + + // If the title must be truncated insert a \0 terminator there + if (length > MAX_TITLE_LENGTH) { + title_w[MAX_TITLE_LENGTH - 1] = *L"\0"; + } + + if (!SetConsoleTitleW(title_w)) { + _winapi_perror("SetConsoleTitleW"); + } + + free(process_title); + process_title = strdup(title); + + delete title_w; +} + + +static inline char* _getProcessTitle() { + WCHAR *title_w; + char *title; + int length, length_w; + + length_w = GetConsoleTitleW(L"\0", sizeof(WCHAR)); + + // If length is zero, there may be an error or the title may be empty + if (!length_w) { + if (GetLastError()) { + _winapi_perror("GetConsoleTitleW"); + return NULL; + } + else { + // The title is empty, so return empty string + process_title = strdup("\0"); + return process_title; + } + } + + // Room for \0 terminator + length_w++; + + title_w = new WCHAR[length_w]; + + if (!GetConsoleTitleW(title_w, length_w * sizeof(WCHAR))) { + _winapi_perror("GetConsoleTitleW"); + delete title_w; + return NULL; + } + + // Find out what the size of the buffer is that we need + length = WideCharToMultiByte(CP_UTF8, 0, title_w, length_w, NULL, 0, NULL, NULL); + if (!length) { + _winapi_perror("WideCharToMultiByte"); + delete title_w; + return NULL; + } + + title = (char *) malloc(length); + if (!title) { + perror("malloc"); + delete title_w; + return NULL; + } + + // Do utf16 -> utf8 conversion here + if (!WideCharToMultiByte(CP_UTF8, 0, title_w, -1, title, length, NULL, NULL)) { + _winapi_perror("WideCharToMultiByte"); + delete title_w; + free(title); + return NULL; + } + + delete title_w; + + return title; +} + + +const char* OS::GetProcessTitle(int *len) { + // If the process_title was never read before nor explicitly set, + // we must query it with getConsoleTitleW + if (!process_title) { + process_title = _getProcessTitle(); + } + + if (process_title) { + *len = strlen(process_title); + return process_title; + } else { + *len = 0; + return NULL; + } +} + + +int OS::GetMemory(size_t *rss, size_t *vsize) { + FILE *f = fopen("/proc/self/stat", "r"); + if (!f) return -1; + + int itmp; + char ctmp; + size_t page_size = getpagesize(); + + /* PID */ + if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Exec file */ + if (fscanf (f, "%s ", buf) == 0) goto error; /* coverity[secure_coding] */ + /* State */ + if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */ + /* Parent process */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Process group */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Session id */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* TTY */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* TTY owner process group */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Flags */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Minor faults (no memory page) */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Minor faults, children */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Major faults (memory page faults) */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Major faults, children */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* utime */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* stime */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* utime, children */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* stime, children */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* jiffies remaining in current time slice */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* 'nice' value */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* jiffies until next timeout */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* jiffies until next SIGALRM */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* start time (jiffies since system boot) */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + + /* Virtual memory size */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + *vsize = (size_t) itmp; + + /* Resident set size */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + *rss = (size_t) itmp * page_size; + + /* rlim */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Start of text */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* End of text */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + /* Start of stack */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ + + fclose (f); + + return 0; + +error: + fclose (f); + return -1; +} + + +int OS::GetExecutablePath(char* buffer, size_t* size) { + *size = readlink("/proc/self/exe", buffer, *size - 1); + if (*size <= 0) return -1; + buffer[*size] = '\0'; + return 0; +} + +} // namespace node