summaryrefslogtreecommitdiff
path: root/lib/win32/emu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/win32/emu.cpp')
-rw-r--r--lib/win32/emu.cpp913
1 files changed, 582 insertions, 331 deletions
diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp
index 17ac698f..00d43122 100644
--- a/lib/win32/emu.cpp
+++ b/lib/win32/emu.cpp
@@ -12,14 +12,20 @@
#include <windows.h>
#include <fcntl.h>
// #include <atlenc.h>
-#include <unistd.h>
+
+#ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
+#ifdef HAVE_PROCESS_H
+ #include <process.h>
+#endif
#include <string>
#include <list>
-//our implimentation for a timer
-//based on a simple thread which sleeps for a
-//period of time
+// our implementation for a timer, based on a
+// simple thread which sleeps for a period of time
+
static bool gFinishTimer;
static CRITICAL_SECTION gLock;
@@ -28,14 +34,14 @@ typedef struct
int countDown;
int interval;
}
-tTimer;
+Timer_t;
-std::list<tTimer> gTimerList;
+std::list<Timer_t> gTimerList;
static void (__cdecl *gTimerFunc) (int) = NULL;
-int setitimer(int type , struct itimerval *timeout, int)
+int setitimer(int type, struct itimerval *timeout, void *arg)
{
- if ( SIGVTALRM == type || ITIMER_VIRTUAL == type )
+ if (ITIMER_VIRTUAL == type)
{
EnterCriticalSection(&gLock);
// we only need seconds for the mo!
@@ -46,7 +52,7 @@ int setitimer(int type , struct itimerval *timeout, int)
}
else
{
- tTimer ourTimer;
+ Timer_t ourTimer;
ourTimer.countDown = timeout->it_value.tv_sec;
ourTimer.interval = timeout->it_interval.tv_sec;
gTimerList.push_back(ourTimer);
@@ -64,12 +70,12 @@ static unsigned int WINAPI RunTimer(LPVOID lpParameter)
while (!gFinishTimer)
{
- std::list<tTimer>::iterator it;
+ std::list<Timer_t>::iterator it;
EnterCriticalSection(&gLock);
for (it = gTimerList.begin(); it != gTimerList.end(); it++)
{
- tTimer& rTimer(*it);
+ Timer_t& rTimer(*it);
rTimer.countDown --;
if (rTimer.countDown == 0)
@@ -92,13 +98,18 @@ static unsigned int WINAPI RunTimer(LPVOID lpParameter)
for (it = gTimerList.begin(); it != gTimerList.end(); it++)
{
- tTimer& rTimer(*it);
+ Timer_t& rTimer(*it);
if (rTimer.countDown == -1)
{
gTimerList.erase(it);
- //if we don't do this the search is on a corrupt list
+
+ // the iterator is now invalid, so restart search
it = gTimerList.begin();
+
+ // if the list is now empty, don't try to increment
+ // the iterator again
+ if (it == gTimerList.end()) break;
}
}
@@ -148,7 +159,8 @@ bool EnableBackupRights( void )
TOKEN_ADJUST_PRIVILEGES,
&hToken ))
{
- printf( "Cannot open process token - err = %d\n", GetLastError( ) );
+ printf( "Cannot open process token: error %d\n",
+ (int)GetLastError() );
return false;
}
@@ -159,7 +171,8 @@ bool EnableBackupRights( void )
SE_BACKUP_NAME, //the name of the privilege
&( token_priv.Privileges[0].Luid )) ) //result
{
- printf( "Cannot lookup backup privilege - err = %d\n", GetLastError( ) );
+ printf( "Cannot lookup backup privilege: error %d\n",
+ (int)GetLastError( ) );
return false;
}
@@ -179,7 +192,8 @@ bool EnableBackupRights( void )
//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
- printf( "Could not enable backup privileges - err = %d\n", GetLastError( ) );
+ printf( "Could not enable backup privileges: error %d\n",
+ (int)GetLastError( ) );
return false;
}
@@ -192,115 +206,342 @@ bool EnableBackupRights( void )
// --------------------------------------------------------------------------
//
// Function
-// Name: openfile
-// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8
-// Created: 25th October 2004
+// Name: ConvertToWideString
+// Purpose: Converts a string from specified codepage to
+// a wide string (WCHAR*). Returns a buffer which
+// MUST be freed by the caller with delete[].
+// In case of fire, logs the error and returns NULL.
+// Created: 4th February 2006
//
// --------------------------------------------------------------------------
-HANDLE openfile(const char *filename, int flags, int mode)
+WCHAR* ConvertToWideString(const char* pString, unsigned int codepage)
{
- try{
+ int len = MultiByteToWideChar
+ (
+ codepage, // source code page
+ 0, // character-type options
+ pString, // string to map
+ -1, // number of bytes in string - auto detect
+ NULL, // wide-character buffer
+ 0 // size of buffer - work out
+ // how much space we need
+ );
+
+ if (len == 0)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert string to wide string: "
+ "error %d", GetLastError());
+ errno = EINVAL;
+ return NULL;
+ }
- wchar_t *buffer;
- std::string fileN(filename);
+ WCHAR* buffer = new WCHAR[len];
- std::string tmpStr("\\\\?\\");
- //is the path relative or otherwise
- if ( fileN[1] != ':' )
- {
- //we need to get the current directory
- char wd[PATH_MAX];
- if(::getcwd(wd, PATH_MAX) == 0)
- {
- return NULL;
- }
- tmpStr += wd;
- if (tmpStr[tmpStr.length()] != '\\')
- {
- tmpStr += '\\';
- }
- }
- tmpStr += filename;
-
- int strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- tmpStr.c_str(), // string to map
- (int)tmpStr.length(), // number of bytes in string
- NULL, // wide-character buffer
- 0 // size of buffer - work out how much space we need
- );
-
- buffer = new wchar_t[strlen+1];
- if ( buffer == NULL )
- {
- return NULL;
- }
+ if (buffer == NULL)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert string to wide string: "
+ "out of memory");
+ errno = ENOMEM;
+ return NULL;
+ }
- strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- tmpStr.c_str(), // string to map
- (int)tmpStr.length(), // number of bytes in string
- buffer, // wide-character buffer
- strlen // size of buffer
- );
+ len = MultiByteToWideChar
+ (
+ codepage, // source code page
+ 0, // character-type options
+ pString, // string to map
+ -1, // number of bytes in string - auto detect
+ buffer, // wide-character buffer
+ len // size of buffer
+ );
+
+ if (len == 0)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert string to wide string: "
+ "error %i", GetLastError());
+ errno = EACCES;
+ delete [] buffer;
+ return NULL;
+ }
- if ( strlen == 0 )
- {
- delete [] buffer;
- return NULL;
- }
+ return buffer;
+}
- buffer[strlen] = L'\0';
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ConvertUtf8ToWideString
+// Purpose: Converts a string from UTF-8 to a wide string.
+// Returns a buffer which MUST be freed by the caller
+// with delete[].
+// In case of fire, logs the error and returns NULL.
+// Created: 4th February 2006
+//
+// --------------------------------------------------------------------------
+WCHAR* ConvertUtf8ToWideString(const char* pString)
+{
+ return ConvertToWideString(pString, CP_UTF8);
+}
- //flags could be O_WRONLY | O_CREAT | O_RDONLY
- DWORD createDisposition = OPEN_EXISTING;
- DWORD shareMode = FILE_SHARE_READ;
- DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA;
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ConvertFromWideString
+// Purpose: Converts a wide string to a narrow string in the
+// specified code page. Returns a buffer which MUST
+// be freed by the caller with delete[].
+// In case of fire, logs the error and returns NULL.
+// Created: 4th February 2006
+//
+// --------------------------------------------------------------------------
+char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage)
+{
+ int len = WideCharToMultiByte
+ (
+ codepage, // destination code page
+ 0, // character-type options
+ pString, // string to map
+ -1, // number of bytes in string - auto detect
+ NULL, // output buffer
+ 0, // size of buffer - work out
+ // how much space we need
+ NULL, // replace unknown chars with system default
+ NULL // don't tell us when that happened
+ );
+
+ if (len == 0)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert wide string to narrow: "
+ "error %d", GetLastError());
+ errno = EINVAL;
+ return NULL;
+ }
- if ( flags & O_WRONLY )
- {
- createDisposition = OPEN_EXISTING;
- shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE;
- }
- if ( flags & O_CREAT )
+ char* buffer = new char[len];
+
+ if (buffer == NULL)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert wide string to narrow: "
+ "out of memory");
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ len = WideCharToMultiByte
+ (
+ codepage, // source code page
+ 0, // character-type options
+ pString, // string to map
+ -1, // number of bytes in string - auto detect
+ buffer, // output buffer
+ len, // size of buffer
+ NULL, // replace unknown chars with system default
+ NULL // don't tell us when that happened
+ );
+
+ if (len == 0)
+ {
+ ::syslog(LOG_WARNING,
+ "Failed to convert wide string to narrow: "
+ "error %i", GetLastError());
+ errno = EACCES;
+ delete [] buffer;
+ return NULL;
+ }
+
+ return buffer;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ConvertUtf8ToConsole
+// Purpose: Converts a string from UTF-8 to the console
+// code page. On success, replaces contents of rDest
+// and returns true. In case of fire, logs the error
+// and returns false.
+// Created: 4th February 2006
+//
+// --------------------------------------------------------------------------
+bool ConvertUtf8ToConsole(const char* pString, std::string& rDest)
+{
+ WCHAR* pWide = ConvertToWideString(pString, CP_UTF8);
+ if (pWide == NULL)
+ {
+ return false;
+ }
+
+ char* pConsole = ConvertFromWideString(pWide, GetConsoleOutputCP());
+ delete [] pWide;
+
+ if (!pConsole)
+ {
+ return false;
+ }
+
+ rDest = pConsole;
+ delete [] pConsole;
+
+ return true;
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ConvertConsoleToUtf8
+// Purpose: Converts a string from the console code page
+// to UTF-8. On success, replaces contents of rDest
+// and returns true. In case of fire, logs the error
+// and returns false.
+// Created: 4th February 2006
+//
+// --------------------------------------------------------------------------
+bool ConvertConsoleToUtf8(const char* pString, std::string& rDest)
+{
+ WCHAR* pWide = ConvertToWideString(pString, GetConsoleCP());
+ if (pWide == NULL)
+ {
+ return false;
+ }
+
+ char* pConsole = ConvertFromWideString(pWide, CP_UTF8);
+ delete [] pWide;
+
+ if (!pConsole)
+ {
+ return false;
+ }
+
+ rDest = pConsole;
+ delete [] pConsole;
+
+ return true;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: ConvertPathToAbsoluteUnicode
+// Purpose: Converts relative paths to absolute (with unicode marker)
+// Created: 4th February 2006
+//
+// --------------------------------------------------------------------------
+std::string ConvertPathToAbsoluteUnicode(const char *pFileName)
+{
+ std::string tmpStr("\\\\?\\");
+
+ // Is the path relative or absolute?
+ // Absolute paths on Windows are always a drive letter
+ // followed by ':'
+
+ if (pFileName[1] != ':')
+ {
+ // Must be relative. We need to get the
+ // current directory to make it absolute.
+
+ char wd[PATH_MAX];
+ if (::getcwd(wd, PATH_MAX) == 0)
{
- createDisposition = OPEN_ALWAYS;
- shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE;
- accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA | FILE_ALL_ACCESS;
+ ::syslog(LOG_WARNING,
+ "Failed to open '%s': path too long",
+ pFileName);
+ errno = ENAMETOOLONG;
+ tmpStr = "";
+ return tmpStr;
}
- if ( flags & O_TRUNC )
+
+ tmpStr += wd;
+ if (tmpStr[tmpStr.length()] != '\\')
{
- createDisposition = OPEN_ALWAYS;
+ tmpStr += '\\';
}
+ }
+
+ tmpStr += pFileName;
+ return tmpStr;
+}
- HANDLE hdir = CreateFileW(buffer,
- accessRights,
- shareMode,
- NULL,
- createDisposition,
- FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
-
- if ( hdir == INVALID_HANDLE_VALUE )
- {
- // DWORD err = GetLastError();
- // syslog(EVENTLOG_WARNING_TYPE, "Couldn't open file %s, err %i\n", filename, err);
- delete [] buffer;
- return NULL;
- }
+// --------------------------------------------------------------------------
+//
+// Function
+// Name: openfile
+// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8
+// Created: 25th October 2004
+//
+// --------------------------------------------------------------------------
+HANDLE openfile(const char *pFileName, int flags, int mode)
+{
+ std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName);
+
+ if (AbsPathWithUnicode.size() == 0)
+ {
+ // error already logged by ConvertPathToAbsoluteUnicode()
+ return NULL;
+ }
+
+ WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
+ // We are responsible for freeing pBuffer
+
+ if (pBuffer == NULL)
+ {
+ // error already logged by ConvertUtf8ToWideString()
+ return NULL;
+ }
- delete [] buffer;
- return hdir;
+ // flags could be O_WRONLY | O_CREAT | O_RDONLY
+ DWORD createDisposition = OPEN_EXISTING;
+ DWORD shareMode = FILE_SHARE_READ;
+ DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA;
+ if (flags & O_WRONLY)
+ {
+ shareMode = FILE_SHARE_WRITE;
}
- catch(...)
+ if (flags & O_RDWR)
{
- printf("Caught openfile:%s\r\n", filename);
+ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+ if (flags & O_CREAT)
+ {
+ createDisposition = OPEN_ALWAYS;
+ shareMode |= FILE_SHARE_WRITE;
+ accessRights |= FILE_WRITE_ATTRIBUTES
+ | FILE_WRITE_DATA | FILE_WRITE_EA
+ | FILE_ALL_ACCESS;
+ }
+ if (flags & O_TRUNC)
+ {
+ createDisposition = CREATE_ALWAYS;
+ }
+ if (flags & O_EXCL)
+ {
+ shareMode = 0;
+ }
+
+ HANDLE hdir = CreateFileW(pBuffer,
+ accessRights,
+ shareMode,
+ NULL,
+ createDisposition,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ delete [] pBuffer;
+
+ if (hdir == INVALID_HANDLE_VALUE)
+ {
+ ::syslog(LOG_WARNING, "Failed to open file %s: "
+ "error %i", pFileName, GetLastError());
+ return NULL;
}
- return NULL;
+ return hdir;
}
// MinGW provides a getopt implementation
@@ -315,18 +556,18 @@ char nextchar = -1;
// --------------------------------------------------------------------------
//
// Function
-// Name: ourfstat
+// Name: emu_fstat
// Purpose: replacement for fstat supply a windows handle
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
-int ourfstat(HANDLE hdir, struct stat * st)
+int emu_fstat(HANDLE hdir, struct stat * st)
{
ULARGE_INTEGER conv;
if (hdir == INVALID_HANDLE_VALUE)
{
- ::syslog(LOG_ERR, "Error: invalid file handle in ourfstat()");
+ ::syslog(LOG_ERR, "Error: invalid file handle in emu_fstat()");
errno = EBADF;
return -1;
}
@@ -343,7 +584,7 @@ int ourfstat(HANDLE hdir, struct stat * st)
// This next example is how we get our INODE (equivalent) information
conv.HighPart = fi.nFileIndexHigh;
conv.LowPart = fi.nFileIndexLow;
- st->st_ino = conv.QuadPart;
+ st->st_ino = (_ino_t)conv.QuadPart;
// get the time information
st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime);
@@ -362,7 +603,7 @@ int ourfstat(HANDLE hdir, struct stat * st)
conv.HighPart = st_size.HighPart;
conv.LowPart = st_size.LowPart;
- st->st_size = conv.QuadPart;
+ st->st_size = (_off_t)conv.QuadPart;
//the mode of the file
st->st_mode = 0;
@@ -400,76 +641,26 @@ int ourfstat(HANDLE hdir, struct stat * st)
// Created: 10th December 2004
//
// --------------------------------------------------------------------------
-HANDLE OpenFileByNameUtf8(const char* pName)
+HANDLE OpenFileByNameUtf8(const char* pFileName)
{
- //some string thing - required by ms to indicate long/unicode filename
- std::string tmpStr("\\\\?\\");
-
- // is the path relative or otherwise
- std::string fileN(pName);
- if (fileN[1] != ':')
- {
- // we need to get the current directory
- char wd[PATH_MAX];
- if(::getcwd(wd, PATH_MAX) == 0)
- {
- ::syslog(LOG_WARNING,
- "Failed to open '%s': path too long", pName);
- errno = ENAMETOOLONG;
- return NULL;
- }
-
- tmpStr += wd;
- if (tmpStr[tmpStr.length()] != '\\')
- {
- tmpStr += '\\';
- }
- }
-
- tmpStr += fileN;
-
- int strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- tmpStr.c_str(), // string to map
- (int)tmpStr.length(), // number of bytes in string
- NULL, // wide-character buffer
- 0 // size of buffer - work out
- // how much space we need
- );
-
- wchar_t* buffer = new wchar_t[strlen+1];
-
- if (buffer == NULL)
+ std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName);
+
+ if (AbsPathWithUnicode.size() == 0)
{
- ::syslog(LOG_WARNING,
- "Failed to open '%s': out of memory", pName);
- errno = ENOMEM;
+ // error already logged by ConvertPathToAbsoluteUnicode()
return NULL;
}
-
- strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- tmpStr.c_str(), // string to map
- (int)tmpStr.length(), // number of bytes in string
- buffer, // wide-character buffer
- strlen // size of buffer
- );
-
- if (strlen == 0)
+
+ WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
+ // We are responsible for freeing pBuffer
+
+ if (pBuffer == NULL)
{
- ::syslog(LOG_WARNING,
- "Failed to open '%s': could not convert "
- "file name to Unicode", pName);
- errno = EACCES;
- delete [] buffer;
+ // error already logged by ConvertUtf8ToWideString()
return NULL;
}
- buffer[strlen] = L'\0';
-
- HANDLE handle = CreateFileW(buffer,
+ HANDLE handle = CreateFileW(pBuffer,
FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
NULL,
@@ -483,7 +674,7 @@ HANDLE OpenFileByNameUtf8(const char* pName)
// open in this mode - to get the inode information
// at least one process must have the file open -
// in this case someone else does.
- handle = CreateFileW(buffer,
+ handle = CreateFileW(pBuffer,
0,
FILE_SHARE_READ,
NULL,
@@ -492,7 +683,7 @@ HANDLE OpenFileByNameUtf8(const char* pName)
NULL);
}
- delete [] buffer;
+ delete [] pBuffer;
if (handle == INVALID_HANDLE_VALUE)
{
@@ -505,7 +696,7 @@ HANDLE OpenFileByNameUtf8(const char* pName)
else
{
::syslog(LOG_WARNING,
- "Failed to open '%s': error %d", pName);
+ "Failed to open '%s': error %d", pFileName, err);
errno = EACCES;
}
@@ -518,13 +709,13 @@ HANDLE OpenFileByNameUtf8(const char* pName)
// --------------------------------------------------------------------------
//
// Function
-// Name: ourstat
+// Name: emu_stat
// Purpose: replacement for the lstat and stat functions,
// works with unicode filenames supplied in utf8 format
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
-int ourstat(const char * pName, struct stat * st)
+int emu_stat(const char * pName, struct stat * st)
{
// at the mo
st->st_uid = 0;
@@ -539,7 +730,7 @@ int ourstat(const char * pName, struct stat * st)
return -1;
}
- int retVal = ourfstat(handle, st);
+ int retVal = emu_fstat(handle, st);
if (retVal != 0)
{
// error logged, but without filename
@@ -593,14 +784,6 @@ int statfs(const char * pName, struct statfs * s)
return 0;
}
-
-
-
-
-// MinGW provides opendir(), etc. via <dirent.h>
-// MSVC does not provide these, so emulation is needed
-
-#ifndef __MINGW32__
// --------------------------------------------------------------------------
//
// Function
@@ -611,110 +794,56 @@ int statfs(const char * pName, struct statfs * s)
// --------------------------------------------------------------------------
DIR *opendir(const char *name)
{
- try
+ if (!name || !name[0])
{
- DIR *dir = 0;
- std::string dirName(name);
-
- //append a '\' win32 findfirst is sensitive to this
- if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' )
- {
- dirName += '\\';
- }
-
- //what is the search string? - everything
- dirName += '*';
-
- if(name && name[0])
- {
- if ( ( dir = new DIR ) != 0 )
- {
- //mbstowcs(dir->name, dirName.c_str(),100);
- //wcscpy((wchar_t*)dir->name, (const wchar_t*)dirName.c_str());
- //mbstowcs(dir->name, dirName.c_str(), dirName.size()+1);
- //wchar_t *buffer;
-
- int strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- dirName.c_str(), // string to map
- (int)dirName.length(), // number of bytes in string
- NULL, // wide-character buffer
- 0 // size of buffer - work out how much space we need
- );
-
- dir->name = new wchar_t[strlen+1];
-
- if (dir->name == NULL)
- {
- delete dir;
- dir = 0;
- errno = ENOMEM;
- return NULL;
- }
-
- strlen = MultiByteToWideChar(
- CP_UTF8, // code page
- 0, // character-type options
- dirName.c_str(), // string to map
- (int)dirName.length(), // number of bytes in string
- dir->name, // wide-character buffer
- strlen // size of buffer
- );
+ errno = EINVAL;
+ return NULL;
+ }
+
+ std::string dirName(name);
- if (strlen == 0)
- {
- delete dir->name;
- delete dir;
- dir = 0;
- errno = ENOMEM;
- return NULL;
- }
+ //append a '\' win32 findfirst is sensitive to this
+ if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' )
+ {
+ dirName += '\\';
+ }
- dir->name[strlen] = L'\0';
+ // what is the search string? - everything
+ dirName += '*';
-
- dir->fd = _wfindfirst(
- (const wchar_t*)dir->name,
- &dir->info);
+ DIR *pDir = new DIR;
+ if (pDir == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
- if (dir->fd != -1)
- {
- dir->result.d_name = 0;
- }
- else // go back
- {
- delete [] dir->name;
- delete dir;
- dir = 0;
- }
- }
- else // backwards again
- {
- delete dir;
- dir = 0;
- errno = ENOMEM;
- }
- }
- else
- {
- errno = EINVAL;
- }
+ pDir->name = ConvertUtf8ToWideString(dirName.c_str());
+ // We are responsible for freeing dir->name
+
+ if (pDir->name == NULL)
+ {
+ delete pDir;
+ return NULL;
+ }
- return dir;
+ pDir->fd = _wfindfirst((const wchar_t*)pDir->name, &(pDir->info));
- }
- catch(...)
+ if (pDir->fd == -1)
{
- printf("Caught opendir");
+ delete [] pDir->name;
+ delete pDir;
+ return NULL;
}
-
- return NULL;
+
+ pDir->result.d_name = 0;
+ return pDir;
}
-//this kinda makes it not thread friendly!
-//but I don't think it needs to be.
+// this kinda makes it not thread friendly!
+// but I don't think it needs to be.
char tempbuff[MAX_PATH];
+
// --------------------------------------------------------------------------
//
// Function
@@ -794,7 +923,6 @@ int closedir(DIR *dp)
}
return -1;
}
-#endif // !__MINGW32__
// --------------------------------------------------------------------------
//
@@ -873,11 +1001,12 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout)
}
HANDLE gSyslogH = 0;
+static bool sHaveWarnedEventLogFull = false;
void syslog(int loglevel, const char *frmt, ...)
{
- DWORD errinfo;
- char* buffer;
+ WORD errinfo;
+ char buffer[1024];
std::string sixfour(frmt);
switch (loglevel)
@@ -896,81 +1025,203 @@ void syslog(int loglevel, const char *frmt, ...)
break;
}
-
- //taken from MSDN
- try
+ // taken from MSDN
+ int sixfourpos;
+ while ( (sixfourpos = (int)sixfour.find("%ll")) != -1 )
{
+ // maintain portability - change the 64 bit formater...
+ std::string temp = sixfour.substr(0,sixfourpos);
+ temp += "%I64";
+ temp += sixfour.substr(sixfourpos+3, sixfour.length());
+ sixfour = temp;
+ }
+
+ // printf("parsed string is:%s\r\n", sixfour.c_str());
+
+ va_list args;
+ va_start(args, frmt);
+
+ int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args);
+ ASSERT(len < sizeof(buffer))
+ buffer[sizeof(buffer)-1] = 0;
+
+ va_end(args);
+
+ LPCSTR strings[] = { buffer, NULL };
+ if (!ReportEvent(gSyslogH, // event log handle
+ errinfo, // event type
+ 0, // category zero
+ MSG_ERR_EXIST, // event identifier -
+ // we will call them all the same
+ NULL, // no user security identifier
+ 1, // one substitution string
+ 0, // no data
+ strings, // pointer to string array
+ NULL)) // pointer to data
- int sixfourpos;
- while ( ( sixfourpos = sixfour.find("%ll")) != -1 )
+ {
+ DWORD err = GetLastError();
+ if (err == ERROR_LOG_FILE_FULL)
+ {
+ if (!sHaveWarnedEventLogFull)
+ {
+ printf("Unable to send message to Event Log "
+ "(Event Log is full):\r\n");
+ sHaveWarnedEventLogFull = TRUE;
+ }
+ }
+ else
{
- //maintain portability - change the 64 bit formater...
- std::string temp = sixfour.substr(0,sixfourpos);
- temp += "%I64";
- temp += sixfour.substr(sixfourpos+3, sixfour.length());
- sixfour = temp;
+ printf("Unable to send message to Event Log: "
+ "error %i:\r\n", (int)err);
}
+ }
+ else
+ {
+ sHaveWarnedEventLogFull = false;
+ }
- //printf("parsed string is:%s\r\n", sixfour.c_str());
+ printf("%s\r\n", buffer);
+}
- va_list args;
- va_start(args, frmt);
+int emu_chdir(const char* pDirName)
+{
+ WCHAR* pBuffer = ConvertUtf8ToWideString(pDirName);
+ if (!pBuffer) return -1;
+ int result = SetCurrentDirectoryW(pBuffer);
+ delete [] pBuffer;
+ if (result != 0) return 0;
+ errno = EACCES;
+ return -1;
+}
-#ifdef __MINGW32__
- // no _vscprintf, use a fixed size buffer
- buffer = new char[1024];
- int len = 1023;
-#else
- int len = _vscprintf( sixfour.c_str(), args );
- ASSERT(len > 0)
+char* emu_getcwd(char* pBuffer, int BufSize)
+{
+ DWORD len = GetCurrentDirectoryW(0, NULL);
+ if (len == 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
- len = len + 1;
- char* buffer = new char[len];
-#endif
+ if (len > BufSize)
+ {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
- ASSERT(buffer)
- memset(buffer, 0, len);
+ WCHAR* pWide = new WCHAR [len];
+ if (!pWide)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
- int len2 = vsnprintf(buffer, len, sixfour.c_str(), args);
- ASSERT(len2 <= len);
+ DWORD result = GetCurrentDirectoryW(len, pWide);
+ if (result <= 0 || result >= len)
+ {
+ errno = EACCES;
+ return NULL;
+ }
+
+ char* pUtf8 = ConvertFromWideString(pWide, CP_UTF8);
+ delete [] pWide;
- va_end(args);
+ if (!pUtf8)
+ {
+ return NULL;
}
- catch (...)
+
+ strncpy(pBuffer, pUtf8, BufSize - 1);
+ pBuffer[BufSize - 1] = 0;
+ delete [] pUtf8;
+
+ return pBuffer;
+}
+
+int emu_mkdir(const char* pPathName)
+{
+ WCHAR* pBuffer = ConvertToWideString(pPathName, CP_UTF8);
+ if (!pBuffer)
{
- printf("Caught syslog: %s", sixfour.c_str());
- return;
+ return -1;
}
- try
+ BOOL result = CreateDirectoryW(pBuffer, NULL);
+ delete [] pBuffer;
+
+ if (!result)
{
+ errno = EACCES;
+ return -1;
+ }
- if (!ReportEvent(gSyslogH, // event log handle
- errinfo, // event type
- 0, // category zero
- MSG_ERR_EXIST, // event identifier -
- // we will call them all the same
- NULL, // no user security identifier
- 1, // one substitution string
- 0, // no data
- (LPCSTR*)&buffer, // pointer to string array
- NULL)) // pointer to data
+ return 0;
+}
- {
- DWORD err = GetLastError();
- printf("Unable to send message to Event Log "
- "(error %i):\r\n", err);
- }
+int emu_unlink(const char* pFileName)
+{
+ WCHAR* pBuffer = ConvertToWideString(pFileName, CP_UTF8);
+ if (!pBuffer)
+ {
+ return -1;
+ }
- printf("%s\r\n", buffer);
+ BOOL result = DeleteFileW(pBuffer);
+ delete [] pBuffer;
- if (buffer) delete [] buffer;
+ if (!result)
+ {
+ errno = EACCES;
+ return -1;
}
- catch (...)
+
+ return 0;
+}
+
+int console_read(char* pBuffer, size_t BufferSize)
+{
+ HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (hConsole == INVALID_HANDLE_VALUE)
{
- printf("Caught syslog ReportEvent");
+ ::fprintf(stderr, "Failed to get a handle on standard input: "
+ "error %d\n", GetLastError());
+ return -1;
}
+
+ int WideSize = BufferSize / 5;
+ WCHAR* pWideBuffer = new WCHAR [WideSize];
+
+ if (!pWideBuffer)
+ {
+ ::perror("Failed to allocate wide character buffer");
+ return -1;
+ }
+
+ DWORD numCharsRead = 0;
+
+ if (!ReadConsoleW(
+ hConsole,
+ pWideBuffer,
+ WideSize - 1,
+ &numCharsRead,
+ NULL // reserved
+ ))
+ {
+ ::fprintf(stderr, "Failed to read from console: error %d\n",
+ GetLastError());
+ return -1;
+ }
+
+ pWideBuffer[numCharsRead] = 0;
+
+ char* pUtf8 = ConvertFromWideString(pWideBuffer, GetConsoleCP());
+ strncpy(pBuffer, pUtf8, BufferSize);
+ delete [] pUtf8;
+
+ return strlen(pBuffer);
}
#endif // WIN32