//////////////////////////////////////////////////////////////////////////////// /// @brief some utilities for windows /// /// @file /// /// DISCLAIMER /// /// Copyright 2014 ArangoDB GmbH, Cologne, Germany /// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Dr. Oreste Costa-Panaia /// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany /// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #include #include "win-utils.h" #include #include #include #include #include "Basics/logging.h" #include "Basics/files.h" #include "Basics/StringUtils.h" #include "Basics/tri-strings.h" using namespace std; using namespace triagens::basics; // ............................................................................. // Some global variables which may be required throughout the lifetime of the // server // ............................................................................. _invalid_parameter_handler oldInvalidHandleHandler; _invalid_parameter_handler newInvalidHandleHandler; int ftruncate (int fd, long newSize) { int result = _chsize(fd, newSize); return result; } int getpagesize (void) { static int pageSize = 0; // only define it once if (! pageSize) { // first time, so call the system info function SYSTEM_INFO systemInfo; GetSystemInfo (&systemInfo); pageSize = systemInfo.dwPageSize; } return pageSize; } //////////////////////////////////////////////////////////////////////////////// // Calls the windows Sleep function which always sleeps for milliseconds //////////////////////////////////////////////////////////////////////////////// void TRI_sleep (unsigned long waitTime) { Sleep(waitTime * 1000); } //////////////////////////////////////////////////////////////////////////////// // Calls a timer which waits for a signal after the elapsed time. // The timer is accurate to 100nanoseconds //////////////////////////////////////////////////////////////////////////////// void TRI_usleep (unsigned long waitTime) { int result; HANDLE hTimer = NULL; // stores the handle of the timer object LARGE_INTEGER wTime; // essentially a 64bit number wTime.QuadPart = waitTime * 10; // *10 to change to microseconds wTime.QuadPart = -wTime.QuadPart; // negative indicates relative time elapsed, // Create an unnamed waitable timer. hTimer = CreateWaitableTimer(NULL, 1, NULL); if (hTimer == NULL) { // not much we can do at this low level return; } if (GetLastError() == ERROR_ALREADY_EXISTS) { LOG_FATAL_AND_EXIT("internal error in TRI_usleep()"); } // Set timer to wait for indicated micro seconds. if (! SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) { // not much we can do at this low level CloseHandle(hTimer); return; } // Wait for the timer result = WaitForSingleObject(hTimer, INFINITE); if (result != WAIT_OBJECT_0) { CloseHandle(hTimer); LOG_FATAL_AND_EXIT("couldn't wait for timer in TRI_usleep()"); } CloseHandle(hTimer); // todo: go through what the result is e.g. WAIT_OBJECT_0 return; } //////////////////////////////////////////////////////////////////////////////// // Sets up a handler when invalid (win) handles are passed to a windows function. // This is not of much use since no values can be returned. All we can do // for now is to ignore error and hope it goes away! //////////////////////////////////////////////////////////////////////////////// static void InvalidParameterHandler (const wchar_t* expression, // expression sent to function - NULL const wchar_t* function, // name of function - NULL const wchar_t* file, // file where code resides - NULL unsigned int line, // line within file - NULL uintptr_t pReserved) { // in case microsoft forget something LOG_ERROR("Invalid handle parameter passed"); /* if (expression != 0) { wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = %s\n",expression); } else { wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = NULL\n"); } if (function != 0) { wprintf(L"win-utils.c:InvalidParameterHandler:FUNCTION = %s\n",function); } else { wprintf(L"win-utils.c:InvalidParameterHandler:FUNCTION = NULL\n"); } if (file!= 0) { wprintf(L"win-utils.c:InvalidParameterHandler:FILE = %s\n",file); } else { wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n"); } */ //abort(); // TODO: use the wcstombs_s function to convert wchar to char - since all the above // wchar never will contain 2 byte chars } //////////////////////////////////////////////////////////////////////////////// // Called from the 'main' and performs any initialisation requirements which // are specific to windows. // // If this function returns 0, then no errors encountered. If < 0, then the // calling function should terminate the application. If > 0, then the // calling function should decide what to do. //////////////////////////////////////////////////////////////////////////////// int finaliseWindows (const TRI_win_finalise_e finaliseWhat, const char* data) { int result = 0; // ............................................................................ // The data is used to transport information from the calling function to here // it may be NULL (and will be in most cases) // ............................................................................ switch (finaliseWhat) { case TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL: { result = WSACleanup(); // could this cause error on server termination? if (result != 0) { // can not use LOG_ etc here since the logging may have terminated printf("ERROR: Could not perform a valid Winsock2 cleanup. WSACleanup returned error %d.",result); return -1; } return 0; } default: { // can not use LOG_ etc here since the logging may have terminated printf("ERROR: Invalid windows finalisation called"); return -1; } } return -1; } int initialiseWindows (const TRI_win_initialise_e initialiseWhat, const char* data) { // ............................................................................ // The data is used to transport information from the calling function to here // it may be NULL (and will be in most cases) // ............................................................................ switch (initialiseWhat) { case TRI_WIN_INITIAL_SET_DEBUG_FLAG: { _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF)|_CRTDBG_CHECK_ALWAYS_DF); return 0; } // ........................................................................... // Assign a handler for invalid handles // ........................................................................... case TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER: { newInvalidHandleHandler = InvalidParameterHandler; oldInvalidHandleHandler = _set_invalid_parameter_handler(newInvalidHandleHandler); return 0; } case TRI_WIN_INITIAL_SET_MAX_STD_IO: { int* newMax = (int*)(data); int result = _setmaxstdio(*newMax); if (result != *newMax) { return -1; } return 0; } case TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL: { int errorCode; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2,2); errorCode = WSAStartup(wVersionRequested, &wsaData); if (errorCode != 0) { LOG_ERROR("Could not find a usable Winsock DLL. WSAStartup returned an error."); return -1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { LOG_ERROR("Could not find a usable Winsock DLL. WSAStartup did not return version 2.2."); WSACleanup(); return -1; } return 0; } default: { LOG_ERROR("Invalid windows initialisation called"); return -1; } } return -1; } int TRI_createFile (const char* filename, int openFlags, int modeFlags) { HANDLE fileHandle; int fileDescriptor; fileHandle = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, (openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW, 0, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { return -1; } fileDescriptor = _open_osfhandle((intptr_t) fileHandle, O_RDWR | _O_BINARY); return fileDescriptor; /* #define O_RDONLY _O_RDONLY #define O_WRONLY _O_WRONLY #define O_RDWR _O_RDWR #define O_APPEND _O_APPEND #define O_CREAT _O_CREAT #define O_TRUNC _O_TRUNC #define O_EXCL _O_EXCL #define O_TEXT _O_TEXT #define O_BINARY _O_BINARY #define O_RAW _O_BINARY #define O_TEMPORARY _O_TEMPORARY #define O_NOINHERIT _O_NOINHERIT #define O_SEQUENTIAL _O_SEQUENTIAL #define O_RANDOM _O_RANDOM //filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR */ } //////////////////////////////////////////////////////////////////////////////// /// @brief opens a file for windows /// /// Creates or opens a file using the windows CreateFile method. Notice below we /// have used the method CreateFileA to avoid unicode characters - for now /// anyway. //////////////////////////////////////////////////////////////////////////////// int TRI_OPEN_WIN32 (const char* filename, int openFlags) { static const int O_ACCMODE = 3; HANDLE fileHandle; int fileDescriptor; DWORD mode; switch (openFlags & O_ACCMODE) { case O_RDONLY: mode = GENERIC_READ; break; case O_WRONLY: mode = GENERIC_WRITE; break; case O_RDWR: mode = GENERIC_READ | GENERIC_WRITE; break; } fileHandle = CreateFileA( filename, mode, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { return -1; } fileDescriptor = _open_osfhandle((intptr_t)(fileHandle), (openFlags & O_ACCMODE) | _O_BINARY); return fileDescriptor; } //////////////////////////////////////////////////////////////////////////////// /// @brief fixes the ICU_DATA environment path //////////////////////////////////////////////////////////////////////////////// void TRI_FixIcuDataEnv () { if (getenv("ICU_DATA") != nullptr) { return; } char* p = nullptr; p = TRI_LocateInstallDirectory(); if (p != nullptr) { string e = string("ICU_DATA=") + p + "\\share\\arangodb\\"; e = StringUtils::replace(e, "\\", "\\\\"); putenv(e.c_str()); } else { #ifdef _SYSCONFDIR_ string e = string("ICU_DATA=") + _SYSCONFDIR_ + "..\\..\\bin"; e = StringUtils::replace(e, "\\", "\\\\"); putenv(e.c_str()); #else p = TRI_LocateBinaryPath(nullptr); if (p != nullptr) { string e = string("ICU_DATA=") + p + "\\"; e = StringUtils::replace(e, "\\", "\\\\"); putenv(e.c_str()); } else { putenv("ICU_DATA=.\\\\"); } #endif } if (p != nullptr) { TRI_FreeString(TRI_CORE_MEM_ZONE, p); } } // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" // End: