diff options
Diffstat (limited to 'lib/win32/emu.cpp')
-rw-r--r-- | lib/win32/emu.cpp | 287 |
1 files changed, 197 insertions, 90 deletions
diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index ef237671..1f6392d5 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -32,8 +32,9 @@ bool EnableBackupRights() if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to open process token: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return false; } @@ -45,8 +46,9 @@ bool EnableBackupRights() SE_BACKUP_NAME, //the name of the privilege &( token_priv.Privileges[0].Luid ))) //result { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to lookup backup privilege: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); CloseHandle(hToken); return false; } @@ -68,8 +70,9 @@ bool EnableBackupRights() //this function is a little tricky - if we were adjusting //more than one privilege, it could return success but not //adjust them all - in the general case, you need to trap this + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to enable backup privilege: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); CloseHandle(hToken); return false; @@ -238,9 +241,10 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) if (len == 0) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EINVAL; return NULL; } @@ -270,9 +274,10 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) if (len == 0) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EACCES; delete [] buffer; return NULL; @@ -299,9 +304,10 @@ bool ConvertFromWideString(const std::wstring& rInput, if (len == 0) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EINVAL; return false; } @@ -331,9 +337,10 @@ bool ConvertFromWideString(const std::wstring& rInput, if (len == 0) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EACCES; delete [] buffer; return false; @@ -363,10 +370,11 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage, true); if (pWide == NULL) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to convert string '%s' from " "current code page %d to wide string: %s", rSource.c_str(), sourceCodePage, - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return false; } @@ -528,7 +536,10 @@ std::string GetErrorMessage(DWORD errorCode) if (chars == 0 || pMsgBuf == NULL) { - return std::string("failed to get error message"); + std::ostringstream oss; + oss << "Failed to get error message for error code " << errorCode << ": error " << + GetLastError(); + return oss.str(); } // remove embedded newline @@ -605,7 +616,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) createDisposition = CREATE_NEW; } - if (flags & O_LOCK) + if (flags & BOX_OPEN_LOCK) { shareMode = 0; } @@ -641,7 +652,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) ::syslog(LOG_WARNING, "Failed to open file '%s': " "%s", pFileName, - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return INVALID_HANDLE_VALUE; } @@ -684,16 +695,18 @@ int emu_fstat(HANDLE hdir, struct emu_stat * st) BY_HANDLE_FILE_INFORMATION fi; if (!GetFileInformationByHandle(hdir, &fi)) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to read file information: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EACCES; return -1; } if (INVALID_FILE_ATTRIBUTES == fi.dwFileAttributes) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to get file attributes: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); errno = EACCES; return -1; } @@ -826,10 +839,10 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) if (handle == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); + winerrno = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND || - err == ERROR_PATH_NOT_FOUND) + if (winerrno == ERROR_FILE_NOT_FOUND || + winerrno == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } @@ -837,7 +850,7 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) { ::syslog(LOG_WARNING, "Failed to open '%s': " "%s", pFileName, - GetErrorMessage(err).c_str()); + GetErrorMessage(winerrno).c_str()); errno = EACCES; } @@ -906,9 +919,10 @@ int statfs(const char * pName, struct statfs * s) BY_HANDLE_FILE_INFORMATION fi; if (!GetFileInformationByHandle(handle, &fi)) { + winerrno = GetLastError(); ::syslog(LOG_WARNING, "Failed to get file information " "for '%s': %s", pName, - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); CloseHandle(handle); errno = EACCES; return -1; @@ -961,8 +975,9 @@ int emu_utimes(const char * pName, const struct timeval times[]) if (!SetFileTime(handle, &creationTime, NULL, &modificationTime)) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to set times on '%s': %s", pName, - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); CloseHandle(handle); return 1; } @@ -1004,8 +1019,9 @@ int emu_chmod(const char * pName, mode_t mode) DWORD attribs = GetFileAttributesW(pBuffer); if (attribs == INVALID_FILE_ATTRIBUTES) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to get file attributes of '%s': %s", - pName, GetErrorMessage(GetLastError()).c_str()); + pName, GetErrorMessage(winerrno).c_str()); errno = EACCES; free(pBuffer); return -1; @@ -1022,8 +1038,9 @@ int emu_chmod(const char * pName, mode_t mode) if (!SetFileAttributesW(pBuffer, attribs)) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to set file attributes of '%s': %s", - pName, GetErrorMessage(GetLastError()).c_str()); + pName, GetErrorMessage(winerrno).c_str()); errno = EACCES; free(pBuffer); return -1; @@ -1078,7 +1095,6 @@ DIR *opendir(const char *name) } pDir->fd = FindFirstFileW(pDir->name, &pDir->info); - DWORD tmp = GetLastError(); if (pDir->fd == INVALID_HANDLE_VALUE) { @@ -1297,7 +1313,7 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout) BOOL AddEventSource ( - LPTSTR pszSrcName, // event source name + const std::string& name, // event source name DWORD dwNum // number of categories ) { @@ -1309,8 +1325,9 @@ BOOL AddEventSource if (len == 0) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to get the program file name: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return FALSE; } @@ -1318,31 +1335,39 @@ BOOL AddEventSource std::string regkey("SYSTEM\\CurrentControlSet\\Services\\EventLog\\" "Application\\"); - regkey += pszSrcName; + regkey += name; HKEY hk; DWORD dwDisp; - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(), - 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hk, &dwDisp)) + winerrno = RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(), + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hk, &dwDisp); + if (winerrno == ERROR_ACCESS_DENIED) { - ::syslog(LOG_ERR, "Failed to create the registry key: %s", - GetErrorMessage(GetLastError()).c_str()); + ::syslog(LOG_ERR, "Failed to create the registry key: access denied. You must " + "be an Administrator to register new event sources in %s", regkey.c_str()); + return FALSE; + } + else if (winerrno != ERROR_SUCCESS) + { + ::syslog(LOG_ERR, "Failed to create the registry key: %s: %s", + GetErrorMessage(winerrno).c_str(), regkey.c_str()); return FALSE; } // Set the name of the message file. - if (RegSetValueExW(hk, // subkey handle - L"EventMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE)cmd, // pointer to value data - len*sizeof(WCHAR))) // data size + winerrno = RegSetValueExW(hk, // subkey handle + L"EventMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data + len*sizeof(WCHAR)); // data size + if (winerrno != ERROR_SUCCESS) { ::syslog(LOG_ERR, "Failed to set the event message file: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); RegCloseKey(hk); return FALSE; } @@ -1352,43 +1377,46 @@ BOOL AddEventSource DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; - if (RegSetValueEx(hk, // subkey handle - "TypesSupported", // value name - 0, // must be zero - REG_DWORD, // value type - (LPBYTE) &dwData, // pointer to value data - sizeof(DWORD))) // length of value data + winerrno = RegSetValueEx(hk, // subkey handle + "TypesSupported", // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwData, // pointer to value data + sizeof(DWORD)); // length of value data + if (winerrno != ERROR_SUCCESS) { ::syslog(LOG_ERR, "Failed to set the supported types: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); RegCloseKey(hk); return FALSE; } // Set the category message file and number of categories. - if (RegSetValueExW(hk, // subkey handle - L"CategoryMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE)cmd, // pointer to value data - len*sizeof(WCHAR))) // data size + winerrno = RegSetValueExW(hk, // subkey handle + L"CategoryMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data + len*sizeof(WCHAR)); // data size + if (winerrno != ERROR_SUCCESS) { ::syslog(LOG_ERR, "Failed to set the category message file: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); RegCloseKey(hk); return FALSE; } - if (RegSetValueEx(hk, // subkey handle + winerrno = RegSetValueEx(hk, // subkey handle "CategoryCount", // value name 0, // must be zero REG_DWORD, // value type (LPBYTE) &dwNum, // pointer to value data - sizeof(DWORD))) // length of value data + sizeof(DWORD)); // length of value data + if (winerrno != ERROR_SUCCESS) { ::syslog(LOG_ERR, "Failed to set the category count: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); RegCloseKey(hk); return FALSE; } @@ -1397,7 +1425,7 @@ BOOL AddEventSource return TRUE; } -static HANDLE gSyslogH = 0; +static HANDLE gSyslogH = INVALID_HANDLE_VALUE; static bool sHaveWarnedEventLogFull = false; void openlog(const char * daemonName, int, int) @@ -1406,19 +1434,21 @@ void openlog(const char * daemonName, int, int) nameStr += daemonName; nameStr += ")"; - // register a default event source, so that we can - // log errors with the process of adding or registering our own. + // Don't try to open a new handle when one is already open. It will leak handles. + assert(gSyslogH == INVALID_HANDLE_VALUE); + + // Register a default event source, so that we can log errors with the process of + // adding or registering our own, which follows. If this fails, there's not much we + // can do about it, certainly not send anything to the event log! gSyslogH = RegisterEventSource( NULL, // uses local computer nameStr.c_str()); // source name if (gSyslogH == NULL) { + gSyslogH = INVALID_HANDLE_VALUE; } - char* name = strdup(nameStr.c_str()); - BOOL success = AddEventSource(name, 0); - free(name); - + BOOL success = AddEventSource(nameStr, 0); if (!success) { ::syslog(LOG_ERR, "Failed to add our own event source"); @@ -1428,8 +1458,9 @@ void openlog(const char * daemonName, int, int) HANDLE newSyslogH = RegisterEventSource(NULL, nameStr.c_str()); if (newSyslogH == NULL) { + winerrno = GetLastError(); ::syslog(LOG_ERR, "Failed to register our own event source: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); return; } @@ -1439,7 +1470,11 @@ void openlog(const char * daemonName, int, int) void closelog(void) { - DeregisterEventSource(gSyslogH); + if(gSyslogH != INVALID_HANDLE_VALUE) + { + DeregisterEventSource(gSyslogH); + gSyslogH = INVALID_HANDLE_VALUE; + } } void syslog(int loglevel, const char *frmt, ...) @@ -1494,7 +1529,7 @@ void syslog(int loglevel, const char *frmt, ...) va_end(args); - if (gSyslogH == 0) + if (gSyslogH == INVALID_HANDLE_VALUE) { printf("%s\r\n", buffer); fflush(stdout); @@ -1541,22 +1576,20 @@ void syslog(int loglevel, const char *frmt, ...) if (result == 0) { - DWORD err = GetLastError(); - if (err == ERROR_LOG_FILE_FULL) + winerrno = GetLastError(); + if (winerrno == ERROR_LOG_FILE_FULL) { if (!sHaveWarnedEventLogFull) { printf("Unable to send message to Event Log " - "(Event Log is full):\r\n"); - fflush(stdout); + "(Event Log is full): %s\r\n", buffer); sHaveWarnedEventLogFull = TRUE; } } else { - printf("Unable to send message to Event Log: %s:\r\n", - GetErrorMessage(err).c_str()); - fflush(stdout); + printf("Unable to send message to Event Log: %s: %s\r\n", + GetErrorMessage(winerrno).c_str(), buffer); } } else @@ -1589,8 +1622,9 @@ int emu_chdir(const char* pDirName) if (result != 0) return 0; errno = EACCES; + winerrno = GetLastError(); fprintf(stderr, "Failed to change directory to '%s': %s\n", - pDirName, GetErrorMessage(GetLastError()).c_str()); + pDirName, GetErrorMessage(winerrno).c_str()); return -1; } @@ -1668,6 +1702,74 @@ int emu_mkdir(const char* pPathName) return 0; } +int emu_link(const char* pOldPath, const char* pNewPath) +{ + std::string AbsOldPathWithUnicode = + ConvertPathToAbsoluteUnicode(pOldPath); + + if (AbsOldPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + std::string AbsNewPathWithUnicode = + ConvertPathToAbsoluteUnicode(pNewPath); + + if (AbsNewPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pOldBuffer = ConvertUtf8ToWideString(AbsOldPathWithUnicode.c_str()); + if (!pOldBuffer) + { + return -1; + } + + WCHAR* pNewBuffer = ConvertUtf8ToWideString(AbsNewPathWithUnicode.c_str()); + if (!pNewBuffer) + { + delete [] pOldBuffer; + return -1; + } + + BOOL result = CreateHardLinkW(pNewBuffer, pOldBuffer, NULL); + winerrno = GetLastError(); + delete [] pOldBuffer; + delete [] pNewBuffer; + + if (!result) + { + if (winerrno == ERROR_FILE_NOT_FOUND || + winerrno == ERROR_PATH_NOT_FOUND) + { + errno = ENOENT; + } + else if (winerrno == ERROR_SHARING_VIOLATION) + { + errno = EBUSY; + } + else if (winerrno == ERROR_ACCESS_DENIED) + { + errno = EACCES; + } + else + { + ::syslog(LOG_WARNING, "Failed to hardlink file " + "'%s' to '%s': %s", pOldPath, pNewPath, + GetErrorMessage(winerrno).c_str()); + errno = ENOSYS; + } + + return -1; + } + + return 0; + +} + int emu_unlink(const char* pFileName) { std::string AbsPathWithUnicode = @@ -1686,20 +1788,21 @@ int emu_unlink(const char* pFileName) } BOOL result = DeleteFileW(pBuffer); - DWORD err = GetLastError(); + winerrno = GetLastError(); delete [] pBuffer; if (!result) { - if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + if (winerrno == ERROR_FILE_NOT_FOUND || + winerrno == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } - else if (err == ERROR_SHARING_VIOLATION) + else if (winerrno == ERROR_SHARING_VIOLATION) { errno = EBUSY; } - else if (err == ERROR_ACCESS_DENIED) + else if (winerrno == ERROR_ACCESS_DENIED) { errno = EACCES; } @@ -1707,9 +1810,10 @@ int emu_unlink(const char* pFileName) { ::syslog(LOG_WARNING, "Failed to delete file " "'%s': %s", pFileName, - GetErrorMessage(err).c_str()); + GetErrorMessage(winerrno).c_str()); errno = ENOSYS; } + return -1; } @@ -1751,21 +1855,22 @@ int emu_rename(const char* pOldFileName, const char* pNewFileName) } BOOL result = MoveFileW(pOldBuffer, pNewBuffer); - DWORD err = GetLastError(); + winerrno = GetLastError(); delete [] pOldBuffer; delete [] pNewBuffer; if (!result) { - if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + if (winerrno == ERROR_FILE_NOT_FOUND || + winerrno == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } - else if (err == ERROR_SHARING_VIOLATION) + else if (winerrno == ERROR_SHARING_VIOLATION) { errno = EBUSY; } - else if (err == ERROR_ACCESS_DENIED) + else if (winerrno == ERROR_ACCESS_DENIED) { errno = EACCES; } @@ -1773,7 +1878,7 @@ int emu_rename(const char* pOldFileName, const char* pNewFileName) { ::syslog(LOG_WARNING, "Failed to rename file " "'%s' to '%s': %s", pOldFileName, pNewFileName, - GetErrorMessage(err).c_str()); + GetErrorMessage(winerrno).c_str()); errno = ENOSYS; } return -1; @@ -1788,8 +1893,9 @@ int console_read(char* pBuffer, size_t BufferSize) if (hConsole == INVALID_HANDLE_VALUE) { + winerrno = GetLastError(); ::fprintf(stderr, "Failed to get a handle on standard input: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); return -1; } @@ -1812,8 +1918,9 @@ int console_read(char* pBuffer, size_t BufferSize) NULL // reserved )) { + winerrno = GetLastError(); ::fprintf(stderr, "Failed to read from console: %s\n", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return -1; } @@ -1864,7 +1971,7 @@ int writev(int filedes, const struct iovec *vector, size_t count) return bytes; } -// need this for conversions +// Need this for conversions. Works in UTC. time_t ConvertFileTimeToTime_t(FILETIME *fileTime) { SYSTEMTIME stUTC; @@ -1883,18 +1990,17 @@ time_t ConvertFileTimeToTime_t(FILETIME *fileTime) // timeinfo.tm_yday = ...; timeinfo.tm_year = stUTC.wYear - 1900; - time_t retVal = mktime(&timeinfo) - _timezone; + time_t retVal = _mkgmtime(&timeinfo); return retVal; } bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) { - time_t adjusted = from + _timezone; - struct tm *time_breakdown = gmtime(&adjusted); + struct tm *time_breakdown = gmtime(&from); if (time_breakdown == NULL) { ::syslog(LOG_ERR, "Error: failed to convert time format: " - "%d is not a valid time\n", adjusted); + "%d is not a valid time\n", from); return false; } @@ -1911,8 +2017,9 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) // Convert the last-write time to local time. if (!SystemTimeToFileTime(&stUTC, pTo)) { + winerrno = GetLastError(); syslog(LOG_ERR, "Failed to convert between time formats: %s", - GetErrorMessage(GetLastError()).c_str()); + GetErrorMessage(winerrno).c_str()); return false; } |