#endif
#include <windows.h>
-#ifndef __MINGW32__
-#include <lmcons.h>
-#include <lmerr.h>
-/* ugliness to work around a buggy struct definition in lmwksta.h */
-#undef LPTSTR
-#define LPTSTR LPWSTR
-#include <lmwksta.h>
-#undef LPTSTR
-#define LPTSTR LPSTR
-#include <lmapibuf.h>
-#endif /* __MINGW32__ */
-
/* #include "config.h" */
#define PERLIO_NOT_STDIO 0
int _CRT_glob = 0;
#endif
-#ifdef __BORLANDC__
+#if defined(__MINGW32__)
+# define _stat stat
+#endif
+
+#if defined(__BORLANDC__)
# define _stat stat
# define _utimbuf utimbuf
#endif
#define EXECF_SPAWN 2
#define EXECF_SPAWN_NOWAIT 3
+#if defined(PERL_IMPLICIT_SYS)
+# undef win32_get_privlib
+# define win32_get_privlib g_win32_get_privlib
+# undef win32_get_sitelib
+# define win32_get_sitelib g_win32_get_sitelib
+# undef do_spawn
+# define do_spawn g_do_spawn
+# undef getlogin
+# define getlogin g_getlogin
+#endif
+
#if defined(PERL_OBJECT)
-#undef win32_get_privlib
-#define win32_get_privlib g_win32_get_privlib
-#undef win32_get_sitelib
-#define win32_get_sitelib g_win32_get_sitelib
-#undef do_aspawn
-#define do_aspawn g_do_aspawn
-#undef do_spawn
-#define do_spawn g_do_spawn
-#undef Perl_do_exec
-#define Perl_do_exec g_do_exec
-#undef getlogin
-#define getlogin g_getlogin
+# undef do_aspawn
+# define do_aspawn g_do_aspawn
+# undef Perl_do_exec
+# define Perl_do_exec g_do_exec
#endif
static void get_shell(void);
-static long tokenize(char *str, char **dest, char ***destv);
+static long tokenize(const char *str, char **dest, char ***destv);
int do_spawn2(char *cmd, int exectype);
static BOOL has_shell_metachars(char *ptr);
static long filetime_to_clock(PFILETIME ft);
/* try to get full path to binary (which may be mangled when perl is
* run from a 16-bit app) */
- /*PerlIO_printf(PerlIO_stderr(), "Before %s\n", w32_module_name);*/
+ /*PerlIO_printf(Perl_debug_log, "Before %s\n", w32_module_name);*/
(void)win32_longpath(w32_module_name);
- /*PerlIO_printf(PerlIO_stderr(), "After %s\n", w32_module_name);*/
+ /*PerlIO_printf(Perl_debug_log, "After %s\n", w32_module_name);*/
/* normalize to forward slashes */
ptr = w32_module_name;
return FALSE;
}
-#if !defined(PERL_OBJECT)
+#if !defined(PERL_IMPLICIT_SYS)
/* since the current process environment is being updated in util.c
* the library functions will get the correct environment
*/
* Returns number of words in result buffer.
*/
static long
-tokenize(char *str, char **dest, char ***destv)
+tokenize(const char *str, char **dest, char ***destv)
{
char *retstart = Nullch;
char **retvstart = 0;
* interactive use (which is what most programs look in COMSPEC
* for).
*/
- char* defaultshell = (IsWinNT() ? "cmd.exe /x/c" : "command.com /c");
- char *usershell = getenv("PERL5SHELL");
+ const char* defaultshell = (IsWinNT()
+ ? "cmd.exe /x/c" : "command.com /c");
+ const char *usershell = getenv("PERL5SHELL");
w32_perlshell_items = tokenize(usershell ? usershell : defaultshell,
&w32_perlshell_tokens,
&w32_perlshell_vec);
win32_opendir(char *filename)
{
dTHXo;
- DIR *p;
+ DIR *dirp;
long len;
long idx;
char scanname[MAX_PATH+3];
HANDLE fh;
char buffer[MAX_PATH*2];
WCHAR wbuffer[MAX_PATH];
- char* ptr;
+ char* ptr;
len = strlen(filename);
if (len > MAX_PATH)
return NULL;
/* Get us a DIR structure */
- Newz(1303, p, 1, DIR);
- if (p == NULL)
- return NULL;
+ Newz(1303, dirp, 1, DIR);
/* Create the search pattern */
strcpy(scanname, filename);
else {
fh = FindFirstFileA(scanname, &aFindData);
}
+ dirp->handle = fh;
if (fh == INVALID_HANDLE_VALUE) {
+ DWORD err = GetLastError();
/* FindFirstFile() fails on empty drives! */
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- return p;
- Safefree( p);
+ switch (err) {
+ case ERROR_FILE_NOT_FOUND:
+ return dirp;
+ case ERROR_NO_MORE_FILES:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ Safefree(dirp);
return NULL;
}
ptr = aFindData.cFileName;
}
idx = strlen(ptr)+1;
- New(1304, p->start, idx, char);
- if (p->start == NULL)
- Perl_croak_nocontext("opendir: malloc failed!\n");
- strcpy(p->start, ptr);
- p->nfiles++;
-
- /* loop finding all the files that match the wildcard
- * (which should be all of them in this directory!).
- * the variable idx should point one past the null terminator
- * of the previous string found.
- */
- while (USING_WIDE()
- ? FindNextFileW(fh, &wFindData)
- : FindNextFileA(fh, &aFindData)) {
- if (USING_WIDE()) {
- W2AHELPER(wFindData.cFileName, buffer, sizeof(buffer));
- }
- /* ptr is set above to the correct area */
- len = strlen(ptr);
- /* bump the string table size by enough for the
- * new name and it's null terminator
- */
- Renew(p->start, idx+len+1, char);
- if (p->start == NULL)
- Perl_croak_nocontext("opendir: malloc failed!\n");
- strcpy(&p->start[idx], ptr);
- p->nfiles++;
- idx += len+1;
- }
- FindClose(fh);
- p->size = idx;
- p->curr = p->start;
- return p;
+ if (idx < 256)
+ dirp->size = 128;
+ else
+ dirp->size = idx;
+ New(1304, dirp->start, dirp->size, char);
+ strcpy(dirp->start, ptr);
+ dirp->nfiles++;
+ dirp->end = dirp->curr = dirp->start;
+ dirp->end += idx;
+ return dirp;
}
DllExport struct direct *
win32_readdir(DIR *dirp)
{
- int len;
- static int dummy = 0;
+ long len;
if (dirp->curr) {
/* first set up the structure to return */
dirp->dirstr.d_namlen = len;
/* Fake an inode */
- dirp->dirstr.d_ino = dummy++;
+ dirp->dirstr.d_ino = dirp->curr - dirp->start;
- /* Now set up for the nDllExport call to readdir */
+ /* Now set up for the next call to readdir */
dirp->curr += len + 1;
- if (dirp->curr >= (dirp->start + dirp->size)) {
- dirp->curr = NULL;
+ if (dirp->curr >= dirp->end) {
+ dTHXo;
+ char* ptr;
+ BOOL res;
+ WIN32_FIND_DATAW wFindData;
+ WIN32_FIND_DATAA aFindData;
+ char buffer[MAX_PATH*2];
+
+ /* finding the next file that matches the wildcard
+ * (which should be all of them in this directory!).
+ */
+ if (USING_WIDE()) {
+ res = FindNextFileW(dirp->handle, &wFindData);
+ if (res) {
+ W2AHELPER(wFindData.cFileName, buffer, sizeof(buffer));
+ ptr = buffer;
+ }
+ }
+ else {
+ res = FindNextFileA(dirp->handle, &aFindData);
+ if (res)
+ ptr = aFindData.cFileName;
+ }
+ if (res) {
+ long endpos = dirp->end - dirp->start;
+ long newsize = endpos + strlen(ptr) + 1;
+ /* bump the string table size by enough for the
+ * new name and it's null terminator */
+ while (newsize > dirp->size) {
+ long curpos = dirp->curr - dirp->start;
+ dirp->size *= 2;
+ Renew(dirp->start, dirp->size, char);
+ dirp->curr = dirp->start + curpos;
+ }
+ strcpy(dirp->start + endpos, ptr);
+ dirp->end = dirp->start + newsize;
+ dirp->nfiles++;
+ }
+ else
+ dirp->curr = NULL;
}
-
return &(dirp->dirstr);
}
else
DllExport long
win32_telldir(DIR *dirp)
{
- return (long) dirp->curr;
+ return (dirp->curr - dirp->start);
}
/* Seekdir moves the string pointer to a previously saved position
- *(Saved by telldir).
+ * (returned by telldir).
*/
DllExport void
win32_seekdir(DIR *dirp, long loc)
{
- dirp->curr = (char *)loc;
+ dirp->curr = dirp->start + loc;
}
/* Rewinddir resets the string pointer to the start */
win32_closedir(DIR *dirp)
{
dTHXo;
+ if (dirp->handle != INVALID_HANDLE_VALUE)
+ FindClose(dirp->handle);
Safefree(dirp->start);
Safefree(dirp);
return 1;
}
else {
/* failed a step, just return without side effects */
- /*PerlIO_printf(PerlIO_stderr(), "Failed to find %s\n", path);*/
+ /*PerlIO_printf(Perl_debug_log, "Failed to find %s\n", path);*/
*start = sep;
return Nullch;
}
return 0;
}
-/* fix utime() so it works on directories in NT
- * thanks to Jan Dubois <jan.dubois@ibm.net>
- */
+/* fix utime() so it works on directories in NT */
static BOOL
filetime_from_time(PFILETIME pFileTime, time_t Time)
{
- struct tm *pTM = gmtime(&Time);
+ struct tm *pTM = localtime(&Time);
SYSTEMTIME SystemTime;
+ FILETIME LocalTime;
if (pTM == NULL)
return FALSE;
SystemTime.wSecond = pTM->tm_sec;
SystemTime.wMilliseconds = 0;
- return SystemTimeToFileTime(&SystemTime, pFileTime);
+ return SystemTimeToFileTime(&SystemTime, &LocalTime) &&
+ LocalFileTimeToFileTime(&LocalTime, pFileTime);
}
DllExport int
return spawnvp(mode, cmdname, (char * const *)argv);
#else
dTHXo;
- DWORD ret;
+ int ret;
void* env;
char* dir;
STARTUPINFO StartupInfo;
if (mode == P_NOWAIT) {
/* asynchronous spawn -- store handle, return PID */
w32_child_handles[w32_num_children] = ProcessInformation.hProcess;
- ret = w32_child_pids[w32_num_children] = ProcessInformation.dwProcessId;
+ w32_child_pids[w32_num_children] = ProcessInformation.dwProcessId;
+ ret = (int)ProcessInformation.dwProcessId;
++w32_num_children;
}
else {
+ DWORD status;
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
- GetExitCodeProcess(ProcessInformation.hProcess, &ret);
+ GetExitCodeProcess(ProcessInformation.hProcess, &status);
+ ret = (int)status;
CloseHandle(ProcessInformation.hProcess);
}
PerlEnv_free_childdir(dir);
Safefree(cmd);
Safefree(fullcmd);
- return (int)ret;
+ return ret;
#endif
}
XS(w32_DomainName)
{
dXSARGS;
-#ifndef HAS_NETWKSTAGETINFO
- /* mingw32 (and Win95) don't have NetWksta*(), so do it the old way */
- char name[256];
- DWORD size = sizeof(name);
+ HINSTANCE hNetApi32 = LoadLibrary("netapi32.dll");
+ DWORD (__stdcall *pfnNetApiBufferFree)(LPVOID Buffer);
+ DWORD (__stdcall *pfnNetWkstaGetInfo)(LPWSTR servername, DWORD level,
+ void *bufptr);
+
+ if (hNetApi32) {
+ pfnNetApiBufferFree = (DWORD (__stdcall *)(void *))
+ GetProcAddress(hNetApi32, "NetApiBufferFree");
+ pfnNetWkstaGetInfo = (DWORD (__stdcall *)(LPWSTR, DWORD, void *))
+ GetProcAddress(hNetApi32, "NetWkstaGetInfo");
+ }
EXTEND(SP,1);
- if (GetUserName(name,&size)) {
- char sid[1024];
- DWORD sidlen = sizeof(sid);
+ if (hNetApi32 && pfnNetWkstaGetInfo && pfnNetApiBufferFree) {
+ /* this way is more reliable, in case user has a local account. */
char dname[256];
DWORD dnamelen = sizeof(dname);
- SID_NAME_USE snu;
- if (LookupAccountName(NULL, name, (PSID)&sid, &sidlen,
- dname, &dnamelen, &snu)) {
- XSRETURN_PV(dname); /* all that for this */
+ struct {
+ DWORD wki100_platform_id;
+ LPWSTR wki100_computername;
+ LPWSTR wki100_langroup;
+ DWORD wki100_ver_major;
+ DWORD wki100_ver_minor;
+ } *pwi;
+ /* NERR_Success *is* 0*/
+ if (0 == pfnNetWkstaGetInfo(NULL, 100, &pwi)) {
+ if (pwi->wki100_langroup && *(pwi->wki100_langroup)) {
+ WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_langroup,
+ -1, (LPSTR)dname, dnamelen, NULL, NULL);
+ }
+ else {
+ WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_computername,
+ -1, (LPSTR)dname, dnamelen, NULL, NULL);
+ }
+ pfnNetApiBufferFree(pwi);
+ FreeLibrary(hNetApi32);
+ XSRETURN_PV(dname);
}
+ FreeLibrary(hNetApi32);
}
-#else
- /* this way is more reliable, in case user has a local account.
- * XXX need dynamic binding of netapi32.dll symbols or this will fail on
- * Win95. Probably makes more sense to move it into libwin32. */
- char dname[256];
- DWORD dnamelen = sizeof(dname);
- PWKSTA_INFO_100 pwi;
- EXTEND(SP,1);
- if (NERR_Success == NetWkstaGetInfo(NULL, 100, (LPBYTE*)&pwi)) {
- if (pwi->wki100_langroup && *(pwi->wki100_langroup)) {
- WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_langroup,
- -1, (LPSTR)dname, dnamelen, NULL, NULL);
- }
- else {
- WideCharToMultiByte(CP_ACP, NULL, pwi->wki100_computername,
- -1, (LPSTR)dname, dnamelen, NULL, NULL);
+ else {
+ /* Win95 doesn't have NetWksta*(), so do it the old way */
+ char name[256];
+ DWORD size = sizeof(name);
+ if (hNetApi32)
+ FreeLibrary(hNetApi32);
+ if (GetUserName(name,&size)) {
+ char sid[1024];
+ DWORD sidlen = sizeof(sid);
+ char dname[256];
+ DWORD dnamelen = sizeof(dname);
+ SID_NAME_USE snu;
+ if (LookupAccountName(NULL, name, (PSID)&sid, &sidlen,
+ dname, &dnamelen, &snu)) {
+ XSRETURN_PV(dname); /* all that for this */
+ }
}
- NetApiBufferFree(pwi);
- XSRETURN_PV(dname);
}
-#endif
XSRETURN_UNDEF;
}