#include <tchar.h>
#ifdef __GNUC__
#define Win32_Winsock
-# ifdef __cplusplus
-#undef __attribute__ /* seems broken in 2.8.0 */
-#define __attribute__(p)
-# endif
#endif
#include <windows.h>
#define do_spawn g_do_spawn
#undef do_exec
#define do_exec g_do_exec
-#undef opendir
-#define opendir g_opendir
-#undef readdir
-#define readdir g_readdir
-#undef telldir
-#define telldir g_telldir
-#undef seekdir
-#define seekdir g_seekdir
-#undef rewinddir
-#define rewinddir g_rewinddir
-#undef closedir
-#define closedir g_closedir
#undef getlogin
#define getlogin g_getlogin
#endif
static void get_shell(void);
static long tokenize(char *str, char **dest, char ***destv);
int do_spawn2(char *cmd, int exectype);
-static BOOL has_redirection(char *ptr);
+static BOOL has_shell_metachars(char *ptr);
static long filetime_to_clock(PFILETIME ft);
static BOOL filetime_from_time(PFILETIME ft, time_t t);
static char * get_emd_part(char *leading, char *trailing, ...);
+static void remove_dead_process(long deceased);
+static long find_pid(int pid);
+static char * qualified_path(const char *cmd);
HANDLE w32_perldll_handle = INVALID_HANDLE_VALUE;
static DWORD w32_platform = (DWORD)-1;
if (retval == ERROR_SUCCESS){
retval = RegQueryValueEx(handle, lpszValueName, 0, &type, NULL, lpDataLen);
if (retval == ERROR_SUCCESS && type == REG_SZ) {
- if (*ptr != NULL) {
+ if (*ptr) {
Renew(*ptr, *lpDataLen, char);
}
else {
retval = RegQueryValueEx(handle, lpszValueName, 0, NULL, (PBYTE)*ptr, lpDataLen);
if (retval != ERROR_SUCCESS) {
Safefree(*ptr);
- *ptr = NULL;
+ *ptr = Nullch;
}
}
RegCloseKey(handle);
GetRegStr(const char *lpszValueName, char** ptr, DWORD* lpDataLen)
{
*ptr = GetRegStrFromKey(HKEY_CURRENT_USER, lpszValueName, ptr, lpDataLen);
- if (*ptr == NULL)
+ if (*ptr == Nullch)
{
*ptr = GetRegStrFromKey(HKEY_LOCAL_MACHINE, lpszValueName, ptr, lpDataLen);
}
static char *
get_emd_part(char *prev_path, char *trailing_path, ...)
{
+ char base[10];
va_list ap;
- char mod_name[MAX_PATH];
+ char mod_name[MAX_PATH+1];
char *ptr;
char *optr;
char *strip;
va_start(ap, trailing_path);
strip = va_arg(ap, char *);
- GetModuleFileName(GetModuleHandle(NULL), mod_name, sizeof(mod_name));
+ sprintf(base, "%5.3f",
+ (double)PERL_REVISION + ((double)PERL_VERSION / (double)1000));
+
+ GetModuleFileName((HMODULE)((w32_perldll_handle == INVALID_HANDLE_VALUE)
+ ? GetModuleHandle(NULL) : w32_perldll_handle),
+ mod_name, sizeof(mod_name));
ptr = strrchr(mod_name, '\\');
while (ptr && strip) {
/* look for directories to skip back */
*ptr = '\0';
ptr = strrchr(mod_name, '\\');
if (!ptr || stricmp(ptr+1, strip) != 0) {
- *optr = '\\';
- ptr = optr;
+ if(!(*strip == '5' && *(ptr+1) == '5' && strncmp(strip, base, 5) == 0
+ && strncmp(ptr+1, base, 5) == 0)) {
+ *optr = '\\';
+ ptr = optr;
+ }
}
strip = va_arg(ap, char *);
}
va_end(ap);
strcpy(++ptr, trailing_path);
- newsize = strlen(mod_name) + 1;
- if (prev_path) {
- oldsize = strlen(prev_path) + 1;
- newsize += oldsize; /* includes plus 1 for ';' */
- Renew(prev_path, newsize, char);
- prev_path[oldsize] = ';';
- strcpy(&prev_path[oldsize], mod_name);
- }
- else {
- New(1311, prev_path, newsize, char);
- strcpy(prev_path, mod_name);
+ /* only add directory if it exists */
+ if(GetFileAttributes(mod_name) != (DWORD) -1) {
+ /* directory exists */
+ newsize = strlen(mod_name) + 1;
+ if (prev_path) {
+ oldsize = strlen(prev_path) + 1;
+ newsize += oldsize; /* includes plus 1 for ';' */
+ Renew(prev_path, newsize, char);
+ prev_path[oldsize-1] = ';';
+ strcpy(&prev_path[oldsize], mod_name);
+ }
+ else {
+ New(1311, prev_path, newsize, char);
+ strcpy(prev_path, mod_name);
+ }
}
return prev_path;
/* $stdlib = $HKCU{"lib-$]"} || $HKLM{"lib-$]"} || $HKCU{"lib"} || $HKLM{"lib"} || ""; */
sprintf(buffer, "%s-%s", stdlib, pl);
path = GetRegStr(buffer, &path, &datalen);
- if (path == NULL)
+ if (!path)
path = GetRegStr(stdlib, &path, &datalen);
/* $stdlib .= ";$EMD/../../lib" */
{
char *sitelib = "sitelib";
char regstr[40];
- char pathstr[MAX_PATH];
+ char pathstr[MAX_PATH+1];
DWORD datalen;
char *path1 = Nullch;
char *path2 = Nullch;
static BOOL
-has_redirection(char *ptr)
+has_shell_metachars(char *ptr)
{
int inquote = 0;
char quote = '\0';
/*
* Scan string looking for redirection (< or >) or pipe
- * characters (|) that are not in a quoted string
+ * characters (|) that are not in a quoted string.
+ * Shell variable interpolation (%VAR%) can also happen inside strings.
*/
while (*ptr) {
switch(*ptr) {
+ case '%':
+ return TRUE;
case '\'':
case '\"':
if (inquote) {
}
while (++mark <= sp) {
- if (*mark && (str = SvPV(*mark, na)))
+ if (*mark && (str = SvPV_nolen(*mark)))
argv[index++] = str;
else
argv[index++] = "";
argv[index++] = 0;
status = win32_spawnvp(flag,
- (const char*)(really ? SvPV(really,na) : argv[0]),
+ (const char*)(really ? SvPV_nolen(really) : argv[0]),
(const char* const*)argv);
- if (status < 0 && errno == ENOEXEC) {
+ if (status < 0 && (errno == ENOEXEC || errno == ENOENT)) {
/* possible shell-builtin, invoke with shell */
int sh_items;
sh_items = w32_perlshell_items;
argv[sh_items] = w32_perlshell_vec[sh_items];
status = win32_spawnvp(flag,
- (const char*)(really ? SvPV(really,na) : argv[0]),
+ (const char*)(really ? SvPV_nolen(really) : argv[0]),
(const char* const*)argv);
}
if (flag != P_NOWAIT) {
if (status < 0) {
- if (dowarn)
+ if (PL_dowarn)
warn("Can't spawn \"%s\": %s", argv[0], strerror(errno));
status = 255 * 256;
}
else
status *= 256;
- statusvalue = status;
+ PL_statusvalue = status;
}
Safefree(argv);
return (status);
/* Save an extra exec if possible. See if there are shell
* metacharacters in it */
- if (!has_redirection(cmd)) {
+ if (!has_shell_metachars(cmd)) {
New(1301,argv, strlen(cmd) / 2 + 2, char*);
New(1302,cmd2, strlen(cmd) + 1, char);
strcpy(cmd2, cmd);
}
if (exectype != EXECF_SPAWN_NOWAIT) {
if (status < 0) {
- if (dowarn)
+ if (PL_dowarn)
warn("Can't %s \"%s\": %s",
(exectype == EXECF_EXEC ? "exec" : "spawn"),
cmd, strerror(errno));
}
else
status *= 256;
- statusvalue = status;
+ PL_statusvalue = status;
}
return (status);
}
* return the pointer to the current file name.
*/
DIR *
-opendir(char *filename)
+win32_opendir(char *filename)
{
DIR *p;
long len;
return NULL;
/* check to see if filename is a directory */
- if (win32_stat(filename, &sbuf) < 0 || (sbuf.st_mode & S_IFDIR) == 0) {
- /* CRT is buggy on sharenames, so make sure it really isn't */
- DWORD r = GetFileAttributes(filename);
- if (r == 0xffffffff || !(r & FILE_ATTRIBUTE_DIRECTORY))
- return NULL;
- }
+ if (win32_stat(filename, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
+ return NULL;
/* Get us a DIR structure */
Newz(1303, p, 1, DIR);
/* do the FindFirstFile call */
fh = FindFirstFile(scanname, &FindData);
if (fh == INVALID_HANDLE_VALUE) {
+ /* FindFirstFile() fails on empty drives! */
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ return p;
+ Safefree( p);
return NULL;
}
* string pointer to the nDllExport entry.
*/
struct direct *
-readdir(DIR *dirp)
+win32_readdir(DIR *dirp)
{
int len;
static int dummy = 0;
/* Telldir returns the current string pointer position */
long
-telldir(DIR *dirp)
+win32_telldir(DIR *dirp)
{
return (long) dirp->curr;
}
*(Saved by telldir).
*/
void
-seekdir(DIR *dirp, long loc)
+win32_seekdir(DIR *dirp, long loc)
{
dirp->curr = (char *)loc;
}
/* Rewinddir resets the string pointer to the start */
void
-rewinddir(DIR *dirp)
+win32_rewinddir(DIR *dirp)
{
dirp->curr = dirp->start;
}
/* free the memory allocated by opendir */
int
-closedir(DIR *dirp)
+win32_closedir(DIR *dirp)
{
Safefree(dirp->start);
Safefree(dirp);
return 0;
}
-int
-kill(int pid, int sig)
+static long
+find_pid(int pid)
{
- HANDLE hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
+ long child;
+ for (child = 0 ; child < w32_num_children ; ++child) {
+ if (w32_child_pids[child] == pid)
+ return child;
+ }
+ return -1;
+}
- if (hProcess == NULL) {
- croak("kill process failed!\n");
+static void
+remove_dead_process(long child)
+{
+ if (child >= 0) {
+ CloseHandle(w32_child_handles[child]);
+ Copy(&w32_child_handles[child+1], &w32_child_handles[child],
+ (w32_num_children-child-1), HANDLE);
+ Copy(&w32_child_pids[child+1], &w32_child_pids[child],
+ (w32_num_children-child-1), DWORD);
+ w32_num_children--;
}
- else {
- if (!TerminateProcess(hProcess, sig))
- croak("kill process failed!\n");
+}
+
+DllExport int
+win32_kill(int pid, int sig)
+{
+ HANDLE hProcess;
+ hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
+ if (hProcess && TerminateProcess(hProcess, sig))
CloseHandle(hProcess);
+ else {
+ errno = EINVAL;
+ return -1;
}
return 0;
}
DllExport int
win32_stat(const char *path, struct stat *buffer)
{
- char t[MAX_PATH];
+ char t[MAX_PATH+1];
const char *p = path;
int l = strlen(path);
int res;
}
}
res = stat(p,buffer);
+ if (res < 0) {
+ /* CRT is buggy on sharenames, so make sure it really isn't.
+ * XXX using GetFileAttributesEx() will enable us to set
+ * buffer->st_*time (but note that's not available on the
+ * Windows of 1995) */
+ DWORD r = GetFileAttributes(p);
+ if (r != 0xffffffff && (r & FILE_ATTRIBUTE_DIRECTORY)) {
+ buffer->st_mode |= S_IFDIR | S_IREAD;
+ errno = 0;
+ if (!(r & FILE_ATTRIBUTE_READONLY))
+ buffer->st_mode |= S_IWRITE | S_IEXEC;
+ return 0;
+ }
+ }
+ else {
+ if (l == 3 && path[l-2] == ':'
+ && (path[l-1] == '\\' || path[l-1] == '/'))
+ {
+ /* The drive can be inaccessible, some _stat()s are buggy */
+ if (!GetVolumeInformation(path,NULL,0,NULL,NULL,NULL,NULL,0)) {
+ errno = ENOENT;
+ return -1;
+ }
+ }
#ifdef __BORLANDC__
- if (res == 0) {
if (S_ISDIR(buffer->st_mode))
buffer->st_mode |= S_IWRITE | S_IEXEC;
else if (S_ISREG(buffer->st_mode)) {
else
buffer->st_mode &= ~S_IEXEC;
}
- }
#endif
+ }
return res;
}
DllExport char *
win32_getenv(const char *name)
{
- static char *curitem = Nullch;
- static DWORD curlen = 512;
+ static char *curitem = Nullch; /* XXX threadead */
+ static DWORD curlen = 0; /* XXX threadead */
DWORD needlen;
- if (!curitem)
+ if (!curitem) {
+ curlen = 512;
New(1305,curitem,curlen,char);
+ }
needlen = GetEnvironmentVariable(name,curitem,curlen);
if (needlen != 0) {
needlen = GetEnvironmentVariable(name,curitem,curlen);
}
}
- else
- {
- /* allow any environment variables that begin with 'PERL5'
- to be stored in the registry
- */
- if(curitem != NULL)
+ else {
+ /* allow any environment variables that begin with 'PERL'
+ to be stored in the registry */
+ if (curitem)
*curitem = '\0';
- if (strncmp(name, "PERL5", 5) == 0) {
- if (curitem != NULL) {
+ if (strncmp(name, "PERL", 4) == 0) {
+ if (curitem) {
Safefree(curitem);
- curitem = NULL;
+ curitem = Nullch;
+ curlen = 0;
}
curitem = GetRegStr(name, &curitem, &curlen);
}
}
- if(curitem != NULL && *curitem == '\0')
+ if (curitem && *curitem == '\0')
return Nullch;
return curitem;
}
+DllExport int
+win32_putenv(const char *name)
+{
+ char* curitem;
+ char* val;
+ int relval = -1;
+ if(name) {
+ New(1309,curitem,strlen(name)+1,char);
+ strcpy(curitem, name);
+ val = strchr(curitem, '=');
+ if(val) {
+ /* The sane way to deal with the environment.
+ * Has these advantages over putenv() & co.:
+ * * enables us to store a truly empty value in the
+ * environment (like in UNIX).
+ * * we don't have to deal with RTL globals, bugs and leaks.
+ * * Much faster.
+ * Why you may want to enable USE_WIN32_RTL_ENV:
+ * * environ[] and RTL functions will not reflect changes,
+ * which might be an issue if extensions want to access
+ * the env. via RTL. This cuts both ways, since RTL will
+ * not see changes made by extensions that call the Win32
+ * functions directly, either.
+ * GSAR 97-06-07
+ */
+ *val++ = '\0';
+ if(SetEnvironmentVariable(curitem, *val ? val : NULL))
+ relval = 0;
+ }
+ Safefree(curitem);
+ }
+ return relval;
+}
+
#endif
static long
}
DllExport int
+win32_waitpid(int pid, int *status, int flags)
+{
+ int retval = -1;
+ if (pid == -1)
+ return win32_wait(status);
+ else {
+ long child = find_pid(pid);
+ if (child >= 0) {
+ HANDLE hProcess = w32_child_handles[child];
+ DWORD waitcode = WaitForSingleObject(hProcess, INFINITE);
+ if (waitcode != WAIT_FAILED) {
+ if (GetExitCodeProcess(hProcess, &waitcode)) {
+ *status = (int)((waitcode & 0xff) << 8);
+ retval = (int)w32_child_pids[child];
+ remove_dead_process(child);
+ return retval;
+ }
+ }
+ else
+ errno = ECHILD;
+ }
+ else {
+ retval = cwait(status, pid, WAIT_CHILD);
+ /* cwait() returns "correctly" on Borland */
+#ifndef __BORLANDC__
+ if (status)
+ *status *= 256;
+#endif
+ }
+ }
+ return retval >= 0 ? pid : retval;
+}
+
+DllExport int
win32_wait(int *status)
{
-#ifdef USE_RTL_WAIT
- return wait(status);
-#else
/* XXX this wait emulation only knows about processes
* spawned via win32_spawnvp(P_NOWAIT, ...).
*/
/* if a child exists, wait for it to die */
waitcode = WaitForMultipleObjects(w32_num_children,
- w32_child_pids,
+ w32_child_handles,
FALSE,
INFINITE);
if (waitcode != WAIT_FAILED) {
i = waitcode - WAIT_ABANDONED_0;
else
i = waitcode - WAIT_OBJECT_0;
- if (GetExitCodeProcess(w32_child_pids[i], &exitcode) ) {
- CloseHandle(w32_child_pids[i]);
+ if (GetExitCodeProcess(w32_child_handles[i], &exitcode) ) {
*status = (int)((exitcode & 0xff) << 8);
retval = (int)w32_child_pids[i];
- Copy(&w32_child_pids[i+1], &w32_child_pids[i],
- (w32_num_children-i-1), HANDLE);
- w32_num_children--;
+ remove_dead_process(i);
return retval;
}
}
FAILED:
errno = GetLastError();
return -1;
-
-#endif
}
static UINT timerid = 0;
return 0;
}
+#if defined(HAVE_DES_FCRYPT) || defined(PERL_OBJECT)
#ifdef HAVE_DES_FCRYPT
-extern char * des_fcrypt(char *cbuf, const char *txt, const char *salt);
+extern char * des_fcrypt(const char *txt, const char *salt, char *cbuf);
+#endif
DllExport char *
win32_crypt(const char *txt, const char *salt)
{
+#ifdef HAVE_DES_FCRYPT
dTHR;
- return des_fcrypt(crypt_buffer, txt, salt);
+ return des_fcrypt(txt, salt, crypt_buffer);
+#else
+ die("The crypt() function is unimplemented due to excessive paranoia.");
+ return Nullch;
+#endif
}
#endif
return _pclose(pf);
#else
-#ifndef USE_RTL_WAIT
- int child;
-#endif
-
int childpid, status;
SV *sv;
win32_fclose(pf);
SvIVX(sv) = 0;
-#ifndef USE_RTL_WAIT
- for (child = 0 ; child < w32_num_children ; ++child) {
- if (w32_child_pids[child] == (HANDLE)childpid) {
- Copy(&w32_child_pids[child+1], &w32_child_pids[child],
- (w32_num_children-child-1), HANDLE);
- w32_num_children--;
- break;
+ if (win32_waitpid(childpid, &status, 0) == -1)
+ return -1;
+
+ return status;
+
+#endif /* USE_RTL_POPEN */
+}
+
+DllExport int
+win32_rename(const char *oname, const char *newname)
+{
+ /* XXX despite what the documentation says about MoveFileEx(),
+ * it doesn't work under Windows95!
+ */
+ if (IsWinNT()) {
+ if (!MoveFileEx(oname,newname,
+ MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) {
+ DWORD err = GetLastError();
+ switch (err) {
+ case ERROR_BAD_NET_NAME:
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_FILENAME_EXCED_RANGE:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_NO_MORE_FILES:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+ default:
+ errno = EACCES;
+ break;
+ }
+ return -1;
}
+ return 0;
}
-#endif
+ else {
+ int retval = 0;
+ char tmpname[MAX_PATH+1];
+ char dname[MAX_PATH+1];
+ char *endname = Nullch;
+ STRLEN tmplen = 0;
+ DWORD from_attr, to_attr;
+
+ /* if oname doesn't exist, do nothing */
+ from_attr = GetFileAttributes(oname);
+ if (from_attr == 0xFFFFFFFF) {
+ errno = ENOENT;
+ return -1;
+ }
- /* wait for the child */
- if (cwait(&status, childpid, WAIT_CHILD) == -1)
- return (-1);
- /* cwait() returns differently on Borland */
-#ifdef __BORLANDC__
- return (((status >> 8) & 0xff) | ((status << 8) & 0xff00));
-#else
- return (status);
-#endif
+ /* if newname exists, rename it to a temporary name so that we
+ * don't delete it in case oname happens to be the same file
+ * (but perhaps accessed via a different path)
+ */
+ to_attr = GetFileAttributes(newname);
+ if (to_attr != 0xFFFFFFFF) {
+ /* if newname is a directory, we fail
+ * XXX could overcome this with yet more convoluted logic */
+ if (to_attr & FILE_ATTRIBUTE_DIRECTORY) {
+ errno = EACCES;
+ return -1;
+ }
+ tmplen = strlen(newname);
+ strcpy(tmpname,newname);
+ endname = tmpname+tmplen;
+ for (; endname > tmpname ; --endname) {
+ if (*endname == '/' || *endname == '\\') {
+ *endname = '\0';
+ break;
+ }
+ }
+ if (endname > tmpname)
+ endname = strcpy(dname,tmpname);
+ else
+ endname = ".";
-#endif /* USE_RTL_POPEN */
+ /* get a temporary filename in same directory
+ * XXX is this really the best we can do? */
+ if (!GetTempFileName((LPCTSTR)endname, "plr", 0, tmpname)) {
+ errno = ENOENT;
+ return -1;
+ }
+ DeleteFile(tmpname);
+
+ retval = rename(newname, tmpname);
+ if (retval != 0) {
+ errno = EACCES;
+ return retval;
+ }
+ }
+
+ /* rename oname to newname */
+ retval = rename(oname, newname);
+
+ /* if we created a temporary file before ... */
+ if (endname != Nullch) {
+ /* ...and rename succeeded, delete temporary file/directory */
+ if (retval == 0)
+ DeleteFile(tmpname);
+ /* else restore it to what it was */
+ else
+ (void)rename(tmpname, newname);
+ }
+ return retval;
+ }
}
DllExport int
return chdir(dir);
}
+static char *
+create_command_line(const char* command, const char * const *args)
+{
+ int index;
+ char *cmd, *ptr, *arg;
+ STRLEN len = strlen(command) + 1;
+
+ for (index = 0; (ptr = (char*)args[index]) != NULL; ++index)
+ len += strlen(ptr) + 1;
+
+ New(1310, cmd, len, char);
+ ptr = cmd;
+ strcpy(ptr, command);
+ ptr += strlen(ptr);
+ *ptr++ = ' ';
+
+ for (index = 0; (arg = (char*)args[index]) != NULL; ++index) {
+ strcpy(ptr, arg);
+ ptr += strlen(ptr);
+ if ((char*)args[index+1] != NULL)
+ *ptr++ = ' ';
+ }
+
+ return cmd;
+}
+
+static char *
+qualified_path(const char *cmd)
+{
+ char *pathstr;
+ char *fullcmd, *curfullcmd;
+ STRLEN cmdlen = 0;
+ int has_slash = 0;
+
+ if (!cmd)
+ return Nullch;
+ fullcmd = (char*)cmd;
+ while (*fullcmd) {
+ if (*fullcmd == '/' || *fullcmd == '\\')
+ has_slash++;
+ fullcmd++;
+ cmdlen++;
+ }
+
+ /* look in PATH */
+ pathstr = win32_getenv("PATH");
+ New(0, fullcmd, MAX_PATH+1, char);
+ curfullcmd = fullcmd;
+
+ while (1) {
+ DWORD res;
+
+ /* start by appending the name to the current prefix */
+ strcpy(curfullcmd, cmd);
+ curfullcmd += cmdlen;
+
+ /* if it doesn't end with '.', or has no extension, try adding
+ * a trailing .exe first */
+ if (cmd[cmdlen-1] != '.'
+ && (cmdlen < 4 || cmd[cmdlen-4] != '.'))
+ {
+ strcpy(curfullcmd, ".exe");
+ res = GetFileAttributes(fullcmd);
+ if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
+ return fullcmd;
+ *curfullcmd = '\0';
+ }
+
+ /* that failed, try the bare name */
+ res = GetFileAttributes(fullcmd);
+ if (res != 0xFFFFFFFF && !(res & FILE_ATTRIBUTE_DIRECTORY))
+ return fullcmd;
+
+ /* quit if no other path exists, or if cmd already has path */
+ if (!pathstr || !*pathstr || has_slash)
+ break;
+
+ /* skip leading semis */
+ while (*pathstr == ';')
+ pathstr++;
+
+ /* build a new prefix from scratch */
+ curfullcmd = fullcmd;
+ while (*pathstr && *pathstr != ';') {
+ if (*pathstr == '"') { /* foo;"baz;etc";bar */
+ pathstr++; /* skip initial '"' */
+ while (*pathstr && *pathstr != '"') {
+ if (curfullcmd-fullcmd < MAX_PATH-cmdlen-5)
+ *curfullcmd++ = *pathstr;
+ pathstr++;
+ }
+ if (*pathstr)
+ pathstr++; /* skip trailing '"' */
+ }
+ else {
+ if (curfullcmd-fullcmd < MAX_PATH-cmdlen-5)
+ *curfullcmd++ = *pathstr;
+ pathstr++;
+ }
+ }
+ if (*pathstr)
+ pathstr++; /* skip trailing semi */
+ if (curfullcmd > fullcmd /* append a dir separator */
+ && curfullcmd[-1] != '/' && curfullcmd[-1] != '\\')
+ {
+ *curfullcmd++ = '\\';
+ }
+ }
+GIVE_UP:
+ Safefree(fullcmd);
+ return Nullch;
+}
+
+/* XXX this needs to be made more compatible with the spawnvp()
+ * provided by the various RTLs. In particular, searching for
+ * *.{com,bat,cmd} files (as done by the RTLs) is unimplemented.
+ * This doesn't significantly affect perl itself, because we
+ * always invoke things using PERL5SHELL if a direct attempt to
+ * spawn the executable fails.
+ *
+ * XXX splitting and rejoining the commandline between do_aspawn()
+ * and win32_spawnvp() could also be avoided.
+ */
+
DllExport int
win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
{
- int status;
+#ifdef USE_RTL_SPAWNVP
+ return spawnvp(mode, cmdname, (char * const *)argv);
+#else
+ DWORD ret;
+ STARTUPINFO StartupInfo;
+ PROCESS_INFORMATION ProcessInformation;
+ DWORD create = 0;
+
+ char *cmd = create_command_line(cmdname, strcmp(cmdname, argv[0]) == 0
+ ? &argv[1] : argv);
+ char *fullcmd = Nullch;
+
+ switch(mode) {
+ case P_NOWAIT: /* asynch + remember result */
+ if (w32_num_children >= MAXIMUM_WAIT_OBJECTS) {
+ errno = EAGAIN;
+ ret = -1;
+ goto RETVAL;
+ }
+ /* FALL THROUGH */
+ case P_WAIT: /* synchronous execution */
+ break;
+ default: /* invalid mode */
+ errno = EINVAL;
+ ret = -1;
+ goto RETVAL;
+ }
+ memset(&StartupInfo,0,sizeof(StartupInfo));
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.wShowWindow = SW_SHOWDEFAULT;
+
+RETRY:
+ if (!CreateProcess(cmdname, /* search PATH to find executable */
+ cmd, /* executable, and its arguments */
+ NULL, /* process attributes */
+ NULL, /* thread attributes */
+ TRUE, /* inherit handles */
+ create, /* creation flags */
+ NULL, /* inherit environment */
+ NULL, /* inherit cwd */
+ &StartupInfo,
+ &ProcessInformation))
+ {
+ /* initial NULL argument to CreateProcess() does a PATH
+ * search, but it always first looks in the directory
+ * where the current process was started, which behavior
+ * is undesirable for backward compatibility. So we
+ * jump through our own hoops by picking out the path
+ * we really want it to use. */
+ if (!fullcmd) {
+ fullcmd = qualified_path(cmdname);
+ if (fullcmd) {
+ cmdname = fullcmd;
+ goto RETRY;
+ }
+ }
+ errno = ENOENT;
+ ret = -1;
+ goto RETVAL;
+ }
-#ifndef USE_RTL_WAIT
- if (mode == P_NOWAIT && w32_num_children >= MAXIMUM_WAIT_OBJECTS)
- return -1;
-#endif
+ 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_num_children;
+ }
+ else {
+ WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
+ GetExitCodeProcess(ProcessInformation.hProcess, &ret);
+ CloseHandle(ProcessInformation.hProcess);
+ }
- status = spawnvp(mode, cmdname, (char * const *) argv);
-#ifndef USE_RTL_WAIT
- /* XXX For the P_NOWAIT case, Borland RTL returns pinfo.dwProcessId
- * while VC RTL returns pinfo.hProcess. For purposes of the custom
- * implementation of win32_wait(), we assume the latter.
- */
- if (mode == P_NOWAIT && status >= 0)
- w32_child_pids[w32_num_children++] = (HANDLE)status;
+ CloseHandle(ProcessInformation.hThread);
+RETVAL:
+ Safefree(cmd);
+ Safefree(fullcmd);
+ return (int)ret;
#endif
- return status;
+}
+
+DllExport int
+win32_execv(const char *cmdname, const char *const *argv)
+{
+ return execv(cmdname, (char *const *)argv);
}
DllExport int
* then it worked, set PV valid,
* else leave it 'undef'
*/
- if (SvCUR(sv))
- SvPOK_on(sv);
EXTEND(SP,1);
- ST(0) = sv;
- XSRETURN(1);
+ if (SvCUR(sv)) {
+ SvPOK_on(sv);
+ ST(0) = sv;
+ XSRETURN(1);
+ }
+ XSRETURN_UNDEF;
}
static
dXSARGS;
if (items != 1)
croak("usage: Win32::SetCurrentDirectory($cwd)");
- if (SetCurrentDirectory(SvPV(ST(0),na)))
+ if (SetCurrentDirectory(SvPV_nolen(ST(0))))
XSRETURN_YES;
XSRETURN_NO;
dXSARGS;
char ix = 'C';
char root[] = "_:\\";
+
+ EXTEND(SP,1);
while (ix <= 'Z') {
root[0] = ix++;
if (GetDriveType(root) == 1) {
XS(w32_GetLastError)
{
dXSARGS;
+ EXTEND(SP,1);
XSRETURN_IV(GetLastError());
}
static
+XS(w32_SetLastError)
+{
+ dXSARGS;
+ if (items != 1)
+ croak("usage: Win32::SetLastError($error)");
+ SetLastError(SvIV(ST(0)));
+ XSRETURN_EMPTY;
+}
+
+static
XS(w32_LoginName)
{
dXSARGS;
char *name = getlogin_buffer;
DWORD size = sizeof(getlogin_buffer);
+ EXTEND(SP,1);
if (GetUserName(name,&size)) {
/* size includes NULL */
ST(0) = sv_2mortal(newSVpv(name,size-1));
dXSARGS;
char name[MAX_COMPUTERNAME_LENGTH+1];
DWORD size = sizeof(name);
+ EXTEND(SP,1);
if (GetComputerName(name,&size)) {
/* size does NOT include NULL :-( */
ST(0) = sv_2mortal(newSVpv(name,size));
/* mingw32 (and Win95) don't have NetWksta*(), so do it the old way */
char name[256];
DWORD size = sizeof(name);
+ EXTEND(SP,1);
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, &sid, &sidlen,
+ if (LookupAccountName(NULL, name, (PSID)&sid, &sidlen,
dname, &dnamelen, &snu)) {
XSRETURN_PV(dname); /* all that for this */
}
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,
DWORD flags, filecomplen;
if (GetVolumeInformation(NULL, NULL, 0, NULL, &filecomplen,
&flags, fsname, sizeof(fsname))) {
- if (GIMME == G_ARRAY) {
+ if (GIMME_V == G_ARRAY) {
XPUSHs(sv_2mortal(newSVpv(fsname,0)));
XPUSHs(sv_2mortal(newSViv(flags)));
XPUSHs(sv_2mortal(newSViv(filecomplen)));
PUTBACK;
return;
}
+ EXTEND(SP,1);
XSRETURN_PV(fsname);
}
- XSRETURN_UNDEF;
+ XSRETURN_EMPTY;
}
static
PUTBACK;
return;
}
- XSRETURN_UNDEF;
+ XSRETURN_EMPTY;
}
static
XS(w32_IsWinNT)
{
dXSARGS;
+ EXTEND(SP,1);
XSRETURN_IV(IsWinNT());
}
XS(w32_IsWin95)
{
dXSARGS;
+ EXTEND(SP,1);
XSRETURN_IV(IsWin95());
}
if (items != 3)
croak("usage: Win32::Spawn($cmdName, $args, $PID)");
- cmd = SvPV(ST(0),na);
- args = SvPV(ST(1), na);
+ cmd = SvPV_nolen(ST(0));
+ args = SvPV_nolen(ST(1));
memset(&stStartInfo, 0, sizeof(stStartInfo)); /* Clear the block */
stStartInfo.cb = sizeof(stStartInfo); /* Set the structure size */
XS(w32_GetTickCount)
{
dXSARGS;
+ EXTEND(SP,1);
XSRETURN_IV(GetTickCount());
}
if (len) {
SvCUR_set(shortpath,len);
ST(0) = shortpath;
+ XSRETURN(1);
}
- else
- ST(0) = &sv_undef;
- XSRETURN(1);
-}
-
-static
-XS(w32_Sleep)
-{
- dXSARGS;
- if (items != 1)
- croak("usage: Win32::Sleep($milliseconds)");
- Sleep(SvIV(ST(0)));
- XSRETURN_YES;
-}
-
-#define TMPBUFSZ 1024
-#define MAX_LENGTH 2048
-#define SUCCESSRETURNED(x) (x == ERROR_SUCCESS)
-#define REGRETURN(x) XSRETURN_IV(SUCCESSRETURNED(x))
-#define SvHKEY(index) (HKEY)((unsigned long)SvIV(index))
-#define SETIV(index,value) sv_setiv(ST(index), value)
-#define SETNV(index,value) sv_setnv(ST(index), value)
-#define SETPV(index,string) sv_setpv(ST(index), string)
-#define SETPVN(index, buffer, length) sv_setpvn(ST(index), (char*)buffer, length)
-#define SETHKEY(index, hkey) SETIV(index,(long)hkey)
-
-static time_t ft2timet(FILETIME *ft)
-{
- SYSTEMTIME st;
- struct tm tm;
-
- FileTimeToSystemTime(ft, &st);
- tm.tm_sec = st.wSecond;
- tm.tm_min = st.wMinute;
- tm.tm_hour = st.wHour;
- tm.tm_mday = st.wDay;
- tm.tm_mon = st.wMonth - 1;
- tm.tm_year = st.wYear - 1900;
- tm.tm_wday = st.wDayOfWeek;
- tm.tm_yday = -1;
- tm.tm_isdst = -1;
- return mktime (&tm);
-}
-
-static
-XS(w32_RegCloseKey)
-{
- dXSARGS;
-
- if (items != 1)
- {
- croak("usage: Win32::RegCloseKey($hkey);\n");
- }
-
- REGRETURN(RegCloseKey(SvHKEY(ST(0))));
+ XSRETURN_UNDEF;
}
static
-XS(w32_RegConnectRegistry)
+XS(w32_GetFullPathName)
{
dXSARGS;
- HKEY handle;
+ SV *filename;
+ SV *fullpath;
+ char *filepart;
+ DWORD len;
- if (items != 3)
- {
- croak("usage: Win32::RegConnectRegistry($machine, $hkey, $handle);\n");
- }
+ if (items != 1)
+ croak("usage: Win32::GetFullPathName($filename)");
- if (SUCCESSRETURNED(RegConnectRegistry((char *)SvPV(ST(0), na), SvHKEY(ST(1)), &handle)))
- {
- SETHKEY(2,handle);
- XSRETURN_YES;
+ filename = ST(0);
+ fullpath = sv_mortalcopy(filename);
+ SvUPGRADE(fullpath, SVt_PV);
+ do {
+ len = GetFullPathName(SvPVX(filename),
+ SvLEN(fullpath),
+ SvPVX(fullpath),
+ &filepart);
+ } while (len >= SvLEN(fullpath) && sv_grow(fullpath,len+1));
+ if (len) {
+ if (GIMME_V == G_ARRAY) {
+ EXTEND(SP,1);
+ XST_mPV(1,filepart);
+ len = filepart - SvPVX(fullpath);
+ items = 2;
+ }
+ SvCUR_set(fullpath,len);
+ ST(0) = fullpath;
+ XSRETURN(items);
}
- XSRETURN_NO;
+ XSRETURN_EMPTY;
}
static
-XS(w32_RegCreateKey)
+XS(w32_Sleep)
{
dXSARGS;
- HKEY handle;
- DWORD disposition;
- long retval;
-
- if (items != 3)
- {
- croak("usage: Win32::RegCreateKey($hkey, $subkey, $handle);\n");
- }
-
- retval = RegCreateKeyEx(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
- NULL, &handle, &disposition);
-
- if (SUCCESSRETURNED(retval))
- {
- SETHKEY(2,handle);
- XSRETURN_YES;
- }
- XSRETURN_NO;
+ if (items != 1)
+ croak("usage: Win32::Sleep($milliseconds)");
+ Sleep(SvIV(ST(0)));
+ XSRETURN_YES;
}
-static
-XS(w32_RegCreateKeyEx)
+void
+Perl_init_os_extras()
{
- dXSARGS;
-
- unsigned int length;
- long retval;
- HKEY hkey, handle;
- char *subkey;
- char *keyclass;
- DWORD options, disposition;
- REGSAM sam;
- SECURITY_ATTRIBUTES sa, *psa;
-
- if (items != 9)
- {
- croak("usage: Win32::RegCreateKeyEx($hkey, $subkey, $reserved, $class, $options, $sam, "
- "$security, $handle, $disposition);\n");
- }
-
- hkey = SvHKEY(ST(0));
- subkey = (char *)SvPV(ST(1), na);
- keyclass = (char *)SvPV(ST(3), na);
- options = (DWORD) ((unsigned long)SvIV(ST(4)));
- sam = (REGSAM) ((unsigned long)SvIV(ST(5)));
- psa = (SECURITY_ATTRIBUTES*)SvPV(ST(6), length);
- if (length != sizeof(SECURITY_ATTRIBUTES))
- {
- psa = &sa;
- memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- }
-
- retval = RegCreateKeyEx(hkey, subkey, 0, keyclass, options, sam,
- psa, &handle, &disposition);
-
- if (SUCCESSRETURNED(retval))
- {
- if (psa == &sa)
- SETPVN(6, &sa, sizeof(sa));
+ char *file = __FILE__;
+ dXSUB_SYS;
- SETHKEY(7,handle);
- SETIV(8,disposition);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegDeleteKey)
-{
- dXSARGS;
-
- if (items != 2)
- {
- croak("usage: Win32::RegDeleteKey($hkey, $subkey);\n");
- }
-
- REGRETURN(RegDeleteKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na)));
-}
-
-static
-XS(w32_RegDeleteValue)
-{
- dXSARGS;
-
- if (items != 2)
- {
- croak("usage: Win32::RegDeleteValue($hkey, $valname);\n");
- }
-
- REGRETURN(RegDeleteValue(SvHKEY(ST(0)), (char *)SvPV(ST(1), na)));
-}
-
-static
-XS(w32_RegEnumKey)
-{
- dXSARGS;
-
- char keybuffer[TMPBUFSZ];
-
- if (items != 3)
- {
- croak("usage: Win32::RegEnumKey($hkey, $idx, $subkeyname);\n");
- }
-
- if (SUCCESSRETURNED(RegEnumKey(SvHKEY(ST(0)), SvIV(ST(1)), keybuffer, sizeof(keybuffer))))
- {
- SETPV(2, keybuffer);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegEnumKeyEx)
-{
- dXSARGS;
- int length;
-
- DWORD keysz, classsz;
- char keybuffer[TMPBUFSZ];
- char classbuffer[TMPBUFSZ];
- long retval;
- FILETIME filetime;
-
- if (items != 6)
- {
- croak("usage: Win32::RegEnumKeyEx($hkey, $idx, $subkeyname, $reserved, $class, $time);\n");
- }
-
- keysz = sizeof(keybuffer);
- classsz = sizeof(classbuffer);
- retval = RegEnumKeyEx(SvHKEY(ST(0)), SvIV(ST(1)), keybuffer, &keysz, 0,
- classbuffer, &classsz, &filetime);
- if (SUCCESSRETURNED(retval))
- {
- SETPV(2, keybuffer);
- SETPV(4, classbuffer);
- SETIV(5, ft2timet(&filetime));
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegEnumValue)
-{
- dXSARGS;
- HKEY hkey;
- DWORD type, namesz, valsz;
- long retval;
- static HKEY last_hkey;
- char myvalbuf[MAX_LENGTH];
- char mynambuf[MAX_LENGTH];
-
- if (items != 6)
- {
- croak("usage: Win32::RegEnumValue($hkey, $i, $name, $reserved, $type, $value);\n");
- }
-
- hkey = SvHKEY(ST(0));
-
- // If this is a new key, find out how big the maximum name and value sizes are and
- // allocate space for them. Free any old storage and set the old key value to the
- // current key.
-
- if (hkey != (HKEY)last_hkey)
- {
- char keyclass[TMPBUFSZ];
- DWORD classsz, subkeys, maxsubkey, maxclass, values, salen, maxnamesz, maxvalsz;
- FILETIME ft;
- classsz = sizeof(keyclass);
- retval = RegQueryInfoKey(hkey, keyclass, &classsz, 0, &subkeys, &maxsubkey, &maxclass,
- &values, &maxnamesz, &maxvalsz, &salen, &ft);
-
- if (!SUCCESSRETURNED(retval))
- {
- XSRETURN_NO;
- }
- memset(myvalbuf, 0, MAX_LENGTH);
- memset(mynambuf, 0, MAX_LENGTH);
- last_hkey = hkey;
- }
-
- namesz = MAX_LENGTH;
- valsz = MAX_LENGTH;
- retval = RegEnumValue(hkey, SvIV(ST(1)), mynambuf, &namesz, 0, &type, (LPBYTE) myvalbuf, &valsz);
- if (!SUCCESSRETURNED(retval))
- {
- XSRETURN_NO;
- }
- else
- {
- SETPV(2, mynambuf);
- SETIV(4, type);
-
- // return includes the null terminator so delete it if REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ
- switch(type)
- {
- case REG_SZ:
- case REG_MULTI_SZ:
- case REG_EXPAND_SZ:
- if (valsz)
- --valsz;
- case REG_BINARY:
- SETPVN(5, myvalbuf, valsz);
- break;
-
- case REG_DWORD_BIG_ENDIAN:
- {
- BYTE tmp = myvalbuf[0];
- myvalbuf[0] = myvalbuf[3];
- myvalbuf[3] = tmp;
- tmp = myvalbuf[1];
- myvalbuf[1] = myvalbuf[2];
- myvalbuf[2] = tmp;
- }
- case REG_DWORD_LITTLE_ENDIAN: // same as REG_DWORD
- SETNV(5, (double)*((DWORD*)myvalbuf));
- break;
-
- default:
- break;
- }
-
- XSRETURN_YES;
- }
-}
-
-static
-XS(w32_RegFlushKey)
-{
- dXSARGS;
-
- if (items != 1)
- {
- croak("usage: Win32::RegFlushKey($hkey);\n");
- }
-
- REGRETURN(RegFlushKey(SvHKEY(ST(0))));
-}
-
-static
-XS(w32_RegGetKeySecurity)
-{
- dXSARGS;
- SECURITY_DESCRIPTOR sd;
- DWORD sdsz;
-
- if (items != 3)
- {
- croak("usage: Win32::RegGetKeySecurity($hkey, $security_info, $security_descriptor);\n");
- }
-
- if (SUCCESSRETURNED(RegGetKeySecurity(SvHKEY(ST(0)), SvIV(ST(1)), &sd, &sdsz)))
- {
- SETPVN(2, &sd, sdsz);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegLoadKey)
-{
- dXSARGS;
-
- if (items != 3)
- {
- croak("usage: Win32::RegLoadKey($hkey, $subkey, $filename);\n");
- }
-
- REGRETURN(RegLoadKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), (char *)SvPV(ST(2), na)));
-}
-
-static
-XS(w32_RegNotifyChangeKeyValue)
-{
- croak("Win32::RegNotifyChangeKeyValue not yet implemented!\n");
-}
-
-static
-XS(w32_RegOpenKey)
-{
- dXSARGS;
- HKEY handle;
-
- if (items != 3)
- {
- croak("usage: Win32::RegOpenKey($hkey, $subkey, $handle);\n");
- }
-
- if (SUCCESSRETURNED(RegOpenKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), &handle)))
- {
- SETHKEY(2,handle);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegOpenKeyEx)
-{
- dXSARGS;
- HKEY handle;
-
- if (items != 5)
- {
- croak("usage: Win32::RegOpenKeyEx($hkey, $subkey, $reserved, $sam, $handle);\n");
- }
-
- if (SUCCESSRETURNED(RegOpenKeyEx(SvHKEY(ST(0)), (char *)SvPV(ST(1), na),
- 0, (REGSAM) ((unsigned long)SvIV(ST(3))), &handle)))
- {
- SETHKEY(4,handle);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-#pragma optimize("", off)
-static
-XS(w32_RegQueryInfoKey)
-{
- dXSARGS;
- int length;
-
- char keyclass[TMPBUFSZ];
- DWORD subkeys, maxsubkey, maxclass, values, maxvalname, maxvaldata;
- DWORD seclen, classsz;
- FILETIME ft;
- long retval;
-
- if (items != 10)
- {
- croak("usage: Win32::RegQueryInfoKey($hkey, $class, $numsubkeys, $maxsubkey,"
- "$maxclass, $values, $maxvalname, $maxvaldata, $secdesclen,"
- "$lastwritetime);\n");
- }
-
- classsz = sizeof(keyclass);
- retval = RegQueryInfoKey(SvHKEY(ST(0)), keyclass, &classsz, 0, &subkeys, &maxsubkey,
- &maxclass, &values, &maxvalname, &maxvaldata,
- &seclen, &ft);
- if (SUCCESSRETURNED(retval))
- {
- SETPV(1, keyclass);
- SETIV(2, subkeys);
- SETIV(3, maxsubkey);
- SETIV(4, maxclass);
- SETIV(5, values);
- SETIV(6, maxvalname);
- SETIV(7, maxvaldata);
- SETIV(8, seclen);
- SETIV(9, ft2timet(&ft));
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-#pragma optimize("", on)
-
-static
-XS(w32_RegQueryValue)
-{
- dXSARGS;
-
- unsigned char databuffer[TMPBUFSZ*2];
- long datasz = sizeof(databuffer);
-
- if (items != 3)
- {
- croak("usage: Win32::RegQueryValue($hkey, $valuename, $data);\n");
- }
-
- if (SUCCESSRETURNED(RegQueryValue(SvHKEY(ST(0)), SvPV(ST(1), na), (char*)databuffer, &datasz)))
- {
- // return includes the null terminator so delete it
- SETPVN(2, databuffer, --datasz);
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegQueryValueEx)
-{
- dXSARGS;
-
- unsigned char databuffer[TMPBUFSZ*2];
- DWORD datasz = sizeof(databuffer);
- DWORD type;
- LONG result;
- LPBYTE ptr = databuffer;
-
- if (items != 5)
- {
- croak("usage: Win32::RegQueryValueEx($hkey, $valuename, $reserved, $type, $data);\n");
- }
-
- result = RegQueryValueEx(SvHKEY(ST(0)), SvPV(ST(1), na), 0, &type, ptr, &datasz);
- if (result == ERROR_MORE_DATA)
- {
- New(0, ptr, datasz+1, BYTE);
- result = RegQueryValueEx(SvHKEY(ST(0)), SvPV(ST(1), na), 0, &type, ptr, &datasz);
- }
- if (SUCCESSRETURNED(result))
- {
- SETIV(3, type);
-
- // return includes the null terminator so delete it if REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ
- switch(type)
- {
- case REG_SZ:
- case REG_MULTI_SZ:
- case REG_EXPAND_SZ:
- --datasz;
- case REG_BINARY:
- SETPVN(4, ptr, datasz);
- break;
-
- case REG_DWORD_BIG_ENDIAN:
- {
- BYTE tmp = ptr[0];
- ptr[0] = ptr[3];
- ptr[3] = tmp;
- tmp = ptr[1];
- ptr[1] = ptr[2];
- ptr[2] = tmp;
- }
- case REG_DWORD_LITTLE_ENDIAN: // same as REG_DWORD
- SETNV(4, (double)*((DWORD*)ptr));
- break;
-
- default:
- break;
- }
-
- if (ptr != databuffer)
- safefree(ptr);
-
- XSRETURN_YES;
- }
- if (ptr != databuffer)
- safefree(ptr);
-
- XSRETURN_NO;
-}
-
-static
-XS(w32_RegReplaceKey)
-{
- dXSARGS;
-
- if (items != 4)
- {
- croak("usage: Win32::RegReplaceKey($hkey, $subkey, $newfile, $oldfile);\n");
- }
-
- REGRETURN(RegReplaceKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), (char *)SvPV(ST(2), na), (char *)SvPV(ST(3), na)));
-}
-
-static
-XS(w32_RegRestoreKey)
-{
- dXSARGS;
-
- if (items < 2 || items > 3)
- {
- croak("usage: Win32::RegRestoreKey($hkey, $filename [, $flags]);\n");
- }
-
- REGRETURN(RegRestoreKey(SvHKEY(ST(0)), (char*)SvPV(ST(1), na), (DWORD)((items == 3) ? SvIV(ST(2)) : 0)));
-}
-
-static
-XS(w32_RegSaveKey)
-{
- dXSARGS;
-
- if (items != 2)
- {
- croak("usage: Win32::RegSaveKey($hkey, $filename);\n");
- }
-
- REGRETURN(RegSaveKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), NULL));
-}
-
-static
-XS(w32_RegSetKeySecurity)
-{
- dXSARGS;
-
- if (items != 3)
- {
- croak("usage: Win32::RegSetKeySecurity($hkey, $security_info, $security_descriptor);\n");
- }
-
- REGRETURN(RegSetKeySecurity(SvHKEY(ST(0)), SvIV(ST(1)), (SECURITY_DESCRIPTOR*)SvPV(ST(2), na)));
-}
-
-static
-XS(w32_RegSetValue)
-{
- dXSARGS;
-
- unsigned int size;
- char *buffer;
- DWORD type;
-
- if (items != 4)
- {
- croak("usage: Win32::RegSetValue($hkey, $subKey, $type, $data);\n");
- }
-
- type = SvIV(ST(2));
- if (type != REG_SZ && type != REG_EXPAND_SZ)
- {
- croak("Win32::RegSetValue: Type was not REG_SZ or REG_EXPAND_SZ, cannot set %s\n", (char *)SvPV(ST(1), na));
- }
-
- buffer = (char *)SvPV(ST(3), size);
- REGRETURN(RegSetValue(SvHKEY(ST(0)), SvPV(ST(1), na), REG_SZ, buffer, size));
-}
-
-static
-XS(w32_RegSetValueEx)
-{
- dXSARGS;
-
- DWORD type;
- DWORD val;
- unsigned int size;
- char *buffer;
-
- if (items != 5)
- {
- croak("usage: Win32::RegSetValueEx($hkey, $valname, $reserved, $type, $data);\n");
- }
-
- type = (DWORD)SvIV(ST(3));
- switch(type)
- {
- case REG_SZ:
- case REG_BINARY:
- case REG_MULTI_SZ:
- case REG_EXPAND_SZ:
- buffer = (char *)SvPV(ST(4), size);
- if (type != REG_BINARY)
- size++; // include null terminator in size
-
- REGRETURN(RegSetValueEx(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), 0, type, (PBYTE) buffer, size));
- break;
-
- case REG_DWORD_BIG_ENDIAN:
- case REG_DWORD_LITTLE_ENDIAN: // Same as REG_DWORD
- val = (DWORD)SvIV(ST(4));
- REGRETURN(RegSetValueEx(SvHKEY(ST(0)), (char *)SvPV(ST(1), na), 0, type, (PBYTE) &val, sizeof(DWORD)));
- break;
-
- default:
- croak("Win32::RegSetValueEx: Type not specified, cannot set %s\n", (char *)SvPV(ST(1), na));
- }
-}
-
-static
-XS(w32_RegUnloadKey)
-{
- dXSARGS;
-
- if (items != 2)
- {
- croak("usage: Win32::RegUnLoadKey($hkey, $subkey);\n");
- }
-
- REGRETURN(RegUnLoadKey(SvHKEY(ST(0)), (char *)SvPV(ST(1), na)));
-}
-
-static
-XS(w32_RegisterServer)
-{
- dXSARGS;
- BOOL bSuccess = FALSE;
- HINSTANCE hInstance;
- unsigned int length;
- FARPROC sFunc;
-
- if (items != 1)
- {
- croak("usage: Win32::RegisterServer($LibraryName)\n");
- }
-
- hInstance = LoadLibrary((char *)SvPV(ST(0), length));
- if (hInstance != NULL)
- {
- sFunc = GetProcAddress(hInstance, "DllRegisterServer");
- if (sFunc != NULL)
- {
- bSuccess = (sFunc() == 0);
- }
- FreeLibrary(hInstance);
- }
-
- if (bSuccess)
- {
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-static
-XS(w32_UnregisterServer)
-{
- dXSARGS;
- BOOL bSuccess = FALSE;
- HINSTANCE hInstance;
- unsigned int length;
- FARPROC sFunc;
-
- if (items != 1)
- {
- croak("usage: Win32::UnregisterServer($LibraryName)\n");
- }
-
- hInstance = LoadLibrary((char *)SvPV(ST(0), length));
- if (hInstance != NULL)
- {
- sFunc = GetProcAddress(hInstance, "DllUnregisterServer");
- if (sFunc != NULL)
- {
- bSuccess = (sFunc() == 0);
- }
- FreeLibrary(hInstance);
- }
-
- if (bSuccess)
- {
- XSRETURN_YES;
- }
- XSRETURN_NO;
-}
-
-
-void
-Perl_init_os_extras()
-{
- char *file = __FILE__;
- dXSUB_SYS;
-
- w32_perlshell_tokens = Nullch;
- w32_perlshell_items = -1;
- w32_fdpid = newAV(); /* XXX needs to be in Perl_win32_init()? */
-#ifndef USE_RTL_WAIT
- w32_num_children = 0;
-#endif
+ w32_perlshell_tokens = Nullch;
+ w32_perlshell_items = -1;
+ w32_fdpid = newAV(); /* XXX needs to be in Perl_win32_init()? */
+ New(1313, w32_children, 1, child_tab);
+ w32_num_children = 0;
/* these names are Activeware compatible */
newXS("Win32::GetCwd", w32_GetCwd, file);
newXS("Win32::SetCwd", w32_SetCwd, file);
newXS("Win32::GetNextAvailDrive", w32_GetNextAvailDrive, file);
newXS("Win32::GetLastError", w32_GetLastError, file);
+ newXS("Win32::SetLastError", w32_SetLastError, file);
newXS("Win32::LoginName", w32_LoginName, file);
newXS("Win32::NodeName", w32_NodeName, file);
newXS("Win32::DomainName", w32_DomainName, file);
newXS("Win32::Spawn", w32_Spawn, file);
newXS("Win32::GetTickCount", w32_GetTickCount, file);
newXS("Win32::GetShortPathName", w32_GetShortPathName, file);
+ newXS("Win32::GetFullPathName", w32_GetFullPathName, file);
newXS("Win32::Sleep", w32_Sleep, file);
- /* the following extensions are used interally and may be changed at any time */
- /* therefore no documentation is provided */
- newXS("Win32::RegCloseKey", w32_RegCloseKey, file);
- newXS("Win32::RegConnectRegistry", w32_RegConnectRegistry, file);
- newXS("Win32::RegCreateKey", w32_RegCreateKey, file);
- newXS("Win32::RegCreateKeyEx", w32_RegCreateKeyEx, file);
- newXS("Win32::RegDeleteKey", w32_RegDeleteKey, file);
- newXS("Win32::RegDeleteValue", w32_RegDeleteValue, file);
-
- newXS("Win32::RegEnumKey", w32_RegEnumKey, file);
- newXS("Win32::RegEnumKeyEx", w32_RegEnumKeyEx, file);
- newXS("Win32::RegEnumValue", w32_RegEnumValue, file);
-
- newXS("Win32::RegFlushKey", w32_RegFlushKey, file);
- newXS("Win32::RegGetKeySecurity", w32_RegGetKeySecurity, file);
-
- newXS("Win32::RegLoadKey", w32_RegLoadKey, file);
- newXS("Win32::RegOpenKey", w32_RegOpenKey, file);
- newXS("Win32::RegOpenKeyEx", w32_RegOpenKeyEx, file);
- newXS("Win32::RegQueryInfoKey", w32_RegQueryInfoKey, file);
- newXS("Win32::RegQueryValue", w32_RegQueryValue, file);
- newXS("Win32::RegQueryValueEx", w32_RegQueryValueEx, file);
-
- newXS("Win32::RegReplaceKey", w32_RegReplaceKey, file);
- newXS("Win32::RegRestoreKey", w32_RegRestoreKey, file);
- newXS("Win32::RegSaveKey", w32_RegSaveKey, file);
- newXS("Win32::RegSetKeySecurity", w32_RegSetKeySecurity, file);
- newXS("Win32::RegSetValue", w32_RegSetValue, file);
- newXS("Win32::RegSetValueEx", w32_RegSetValueEx, file);
- newXS("Win32::RegUnloadKey", w32_RegUnloadKey, file);
-
- newXS("Win32::RegisterServer", w32_RegisterServer, file);
- newXS("Win32::UnregisterServer", w32_UnregisterServer, file);
-
/* XXX Bloat Alert! The following Activeware preloads really
* ought to be part of Win32::Sys::*, so they're not included
* here.