This is a patch to go from libwin32 v0.16 to v0.171.  This is somewhat
unofficial because I don't have the tuits to make a real release just now,
but since ActivePerl build 618 contains this version of libwin32, I
thought I'd show you what's in it sooner rather than later.

Apply with:

    cd libwin32-0.16
    patch -p1 -N < this_file

Enjoy.

Gurusamy Sarathy
gsar@ActiveState.com
------------------------------------8<------------------------------------
diff -ur libwin32-0.16/APIRegistry/Registry.xs libwin32-0.171/APIRegistry/Registry.xs
--- libwin32-0.16/APIRegistry/Registry.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/APIRegistry/Registry.xs	Tue Sep 19 16:39:21 2000
@@ -484,7 +484,7 @@
 	}
 	RETVAL= ErrorRet( uErr );
 	/* Traim trailing '\0' from REG*_SZ values if iolData was C<[]>: */
-	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType
+	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType  &&  *iolData
 	 &&  ( REG_SZ == *ouType || REG_EXPAND_SZ == *ouType )
 	 &&  null_arg(ST(7))  &&  '\0' == opData[*iolData-1]  )
 	    --*iolData;
@@ -529,6 +529,7 @@
 	RETVAL= ErrorRet( uErr );
 	/* Traim trailing L'\0' from REG*_SZ values if iolData was C<[]>: */
 	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType
+	 &&  *iolData >= sizeof(WCHAR)
 	 &&  ( REG_SZ == *ouType || REG_EXPAND_SZ == *ouType )
 	 &&  null_arg(ST(7))
 	 &&  L'\0' == ((WCHAR *)opData)[(*iolData/sizeof(WCHAR))-1]  )
@@ -901,7 +902,7 @@
 	}
 	RETVAL= ErrorRet( uErr );
 	/* Traim trailing '\0' from REG*_SZ values if iolData was C<[]>: */
-	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType
+	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType  &&  *iolData
 	 &&  ( REG_SZ == *ouType || REG_EXPAND_SZ == *ouType )
 	 &&  null_arg(ST(5))  &&  '\0' == opData[*iolData-1]  )
 	    --*iolData;
@@ -938,6 +939,7 @@
 	RETVAL= ErrorRet( uErr );
 	/* Traim trailing L'\0' from REG*_SZ vals if iolData was C<[]>: */
 	if(  RETVAL  &&  NULL != opData  &&  NULL != ouType
+	 &&  *iolData >= sizeof(WCHAR)
 	 &&  ( REG_SZ == *ouType || REG_EXPAND_SZ == *ouType )
 	 &&  null_arg(ST(5))
 	 &&  L'\0' == ((WCHAR *)opData)[(*iolData/sizeof(WCHAR))-1]  )
diff -ur libwin32-0.16/Changes libwin32-0.171/Changes
--- libwin32-0.16/Changes	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/Changes	Tue Sep 19 16:39:21 2000
@@ -1,6 +1,8 @@
 Revision history for Perl extension libwin32.
 
 
+0.17  (unreleased)
+
 0.16  Mon May 22 22:16:41 2000
 
    + Support for building under Perl 5.6.0.
diff -ur libwin32-0.16/Console/Console.pm libwin32-0.171/Console/Console.pm
--- libwin32-0.16/Console/Console.pm	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/Console/Console.pm	Tue Sep 19 16:39:21 2000
@@ -1,7 +1,7 @@
 package Win32::Console;
 #######################################################################
 #
-# Win32::Console - Perl Module for Windows Clipboard Interaction
+# Win32::Console - Win32 Console and Character Mode Functions
 # ^^^^^^^^^^^^^^
 # Version: 0.03  (07 Apr 1997)
 # Version: 0.031 (24 Sep 1999) - fixed typo in GenerateCtrlEvent()
diff -ur libwin32-0.16/EventLog/Changes libwin32-0.171/EventLog/Changes
--- libwin32-0.16/EventLog/Changes	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/EventLog/Changes	Tue Sep 19 16:39:21 2000
@@ -1,5 +1,9 @@
 Revision history for Perl extension Win32::EventLog.
 
+0.071 Fri Aug 25 12:34:56 2000
+    - remove limit of 16 fields for GetEventLogText
+    - fix endless loop problem in GetEventLogText
+
 0.07  Mon May 22 21:02:26 2000
     - support for passing Unicode strings to underlying calls (thanks
       to Jan Dubois <jand@activestate.com>)
diff -ur libwin32-0.16/EventLog/EventLog.pm libwin32-0.171/EventLog/EventLog.pm
--- libwin32-0.16/EventLog/EventLog.pm	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/EventLog/EventLog.pm	Tue Sep 19 16:39:21 2000
@@ -9,7 +9,7 @@
 
 use strict;
 use vars qw($VERSION $AUTOLOAD @ISA @EXPORT $GetMessageText);
-$VERSION = '0.07';
+$VERSION = '0.071';
 
 require Exporter;
 require DynaLoader;
diff -ur libwin32-0.16/EventLog/EventLog.xs libwin32-0.171/EventLog/EventLog.xs
--- libwin32-0.16/EventLog/EventLog.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/EventLog/EventLog.xs	Tue Sep 19 16:39:21 2000
@@ -417,7 +417,7 @@
     if (USING_WIDE()) {
 	static const WCHAR *wEVFILE[] = {L"System", L"Security", L"Application"};
 	WCHAR *ptr, *tmpx;
-	WCHAR wmsgfile[MAX_PATH], wregPath[MAX_PATH], *wstrings[16];
+	WCHAR wmsgfile[MAX_PATH], wregPath[MAX_PATH], **wstrings;
 	WCHAR wsource[MAX_PATH+1], *wMsgBuf, *wlongstring;
 	char *MsgBuf;
 	DWORD i, id2;
@@ -427,6 +427,8 @@
 	WCHAR *percent;
 	int percentLen, msgLen;
 
+        New(0, wstrings, numstrings+1, WCHAR*);
+
 	/* Which EventLog are we reading? */
 	New(0, wlongstring, length, WCHAR);
 
@@ -480,32 +482,32 @@
 			RegCloseKey(hk);
 			XSRETURN_NO;
 		    }
-
-		    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
-				       | FORMAT_MESSAGE_FROM_HMODULE
-				       | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-				       dll, id2, 0, (LPWSTR)&wMsgBuf, 0,
-				       (va_list*)&wstrings[j]) == 0)
-		    {
-			FreeLibrary(dll);
-			RegCloseKey(hk);
-			XSRETURN_NO;
-		    }
+                }
 
-		    percentLen = 2;	/* for %% */
-		    do {
-			percentLen++;
-		    } while (id2/=10);	/* compute length of %%xxx string */
-
-		    msgLen = wcslen(wMsgBuf);
-		    Newz(0, tmpx, wcslen(wstrings[j])+msgLen-percentLen+1, WCHAR);
-		    wcsncpy(tmpx, wstrings[j], percent-wstrings[j]);
-		    wcsncat(tmpx, wMsgBuf,
-			    msgLen - ((wcscmp(wMsgBuf+msgLen-2, L"\r\n")==0) ? 2 : 0));
-		    wcscat(tmpx, percent+percentLen);
-		    wstrings[j] = tmpx;
-		    LocalFree(wMsgBuf);
-		}
+                if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                   | FORMAT_MESSAGE_FROM_HMODULE
+                                   | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                                   dll, id2, 0, (LPWSTR)&wMsgBuf, 0,
+                                   (va_list*)&wstrings[j]) == 0)
+                {
+                    FreeLibrary(dll);
+                    RegCloseKey(hk);
+                    XSRETURN_NO;
+                }
+
+                percentLen = 2;	/* for %% */
+                do {
+                    percentLen++;
+                } while (id2/=10);	/* compute length of %%xxx string */
+
+                msgLen = wcslen(wMsgBuf);
+                Newz(0, tmpx, wcslen(wstrings[j])+msgLen-percentLen+1, WCHAR);
+                wcsncpy(tmpx, wstrings[j], percent-wstrings[j]);
+                wcsncat(tmpx, wMsgBuf,
+                        msgLen - ((wcscmp(wMsgBuf+msgLen-2, L"\r\n")==0) ? 2 : 0));
+                wcscat(tmpx, percent+percentLen);
+                wstrings[j] = tmpx;
+                LocalFree(wMsgBuf);
 	    }
 	}
 
@@ -541,6 +543,7 @@
 	    if (wstrings[j] < wlongstring || wstrings[j] >= wlongstring+length)
 		Safefree(wstrings[j]);
 	Safefree(wlongstring);
+        Safefree(wstrings);
 
 	if (!result || !wMsgBuf) {
 	    FreeLibrary(dll);
@@ -558,7 +561,7 @@
     }
     else {
 	static const char *EVFILE[] = {"System", "Security", "Application"};
-	char *MsgBuf, *strings[16], *ptr, *tmpx;
+	char *MsgBuf, **strings, *ptr, *tmpx;
 	char msgfile[MAX_PATH], regPath[MAX_PATH];
 	DWORD i, id2;
 	BOOL result;
@@ -567,6 +570,8 @@
 	char *percent;
 	int percentLen, msgLen, gotPercent;
 
+        New(0, strings, numstrings+1, char*);
+
 	/* Which EventLog are we reading? */
 	for (j=0; j < (sizeof(EVFILE)/sizeof(EVFILE[0])); j++) {
 	    sprintf(regPath,
@@ -617,34 +622,34 @@
 			RegCloseKey(hk);
 			XSRETURN_NO;
 		    }
+                }
 
-		    if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
-				       | FORMAT_MESSAGE_FROM_HMODULE
-				       | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-				       dll, id2, 0, (LPSTR)&MsgBuf, 0,
-				       (va_list*)&strings[j]) == 0)
-		    {
-			FreeLibrary(dll);
-			RegCloseKey(hk);
-			XSRETURN_NO;
-		    }
-
-		    percentLen = 2;	/* for %% */
-		    do {
-			percentLen++;
-		    } while (id2/=10);	/* compute length of %%xxx string */
-
-		    msgLen = strlen(MsgBuf);
-		    Newz(0, tmpx, strlen(strings[j])+msgLen-percentLen+1, char);
-		    strncpy(tmpx, strings[j], percent-strings[j]);
-		    strncat(tmpx, MsgBuf,
-			    msgLen - ((strcmp(MsgBuf+msgLen-2, "\r\n")==0) ? 2 : 0));
-		    strcat(tmpx, percent+percentLen);
-		    if (gotPercent)
-			Safefree(strings[j]);
-		    strings[j] = tmpx;
-		    LocalFree(MsgBuf);
-		}
+                if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+                                   | FORMAT_MESSAGE_FROM_HMODULE
+                                   | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                                   dll, id2, 0, (LPSTR)&MsgBuf, 0,
+                                   (va_list*)&strings[j]) == 0)
+                {
+                    FreeLibrary(dll);
+                    RegCloseKey(hk);
+                    XSRETURN_NO;
+                }
+
+                percentLen = 2;	/* for %% */
+                do {
+                    percentLen++;
+                } while (id2/=10);	/* compute length of %%xxx string */
+
+                msgLen = strlen(MsgBuf);
+                Newz(0, tmpx, strlen(strings[j])+msgLen-percentLen+1, char);
+                strncpy(tmpx, strings[j], percent-strings[j]);
+                strncat(tmpx, MsgBuf,
+                        msgLen - ((strcmp(MsgBuf+msgLen-2, "\r\n")==0) ? 2 : 0));
+                strcat(tmpx, percent+percentLen);
+                if (gotPercent)
+                    Safefree(strings[j]);
+                strings[j] = tmpx;
+                LocalFree(MsgBuf);
 	    }
 	}
 
@@ -678,6 +683,8 @@
 	for (j=0; j<=numstrings; j++)
 	    if (strings[j] < longstring || strings[j] >= longstring+length)
 		Safefree(strings[j]);
+
+        Safefree(strings);
 
         if (!result || !MsgBuf) {
 	    FreeLibrary(dll);
diff -ur libwin32-0.16/File/File.xs libwin32-0.171/File/File.xs
--- libwin32-0.16/File/File.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/File/File.xs	Tue Sep 19 16:39:21 2000
@@ -146,7 +146,7 @@
 bool
 GetAttributes(filename,attribs)
 	char *filename
-	DWORD attribs
+	DWORD attribs = NO_INIT
     CODE:
 	if (USING_WIDE()) {
 	    WCHAR wbuffer[MAX_PATH+1];
diff -ur libwin32-0.16/FileSecurity/FileSecurity.xs libwin32-0.171/FileSecurity/FileSecurity.xs
--- libwin32-0.16/FileSecurity/FileSecurity.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/FileSecurity/FileSecurity.xs	Tue Sep 19 16:39:22 2000
@@ -350,7 +350,7 @@
 			    );
 		    }
 
-		    if (bResult) {
+		    if (!bResult) {
 			Name = NoName ;
 			bDName = 0;
 			bName = strlen(Name);
diff -ur libwin32-0.16/Internet/Internet.pm libwin32-0.171/Internet/Internet.pm
--- libwin32-0.16/Internet/Internet.pm	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/Internet/Internet.pm	Tue Sep 19 16:39:22 2000
@@ -1301,8 +1301,8 @@
                                     $version,
                                     $referer,
                                     $accept,
-                                    0,
-                                    $flags);
+                                    $flags,
+				    0);
 
     if($newhandle) {
 
diff -ur libwin32-0.16/Internet/Internet.xs libwin32-0.171/Internet/Internet.xs
--- libwin32-0.16/Internet/Internet.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/Internet/Internet.xs	Tue Sep 19 16:39:22 2000
@@ -398,84 +398,72 @@
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_HYPERLINK"))
 					#ifdef INTERNET_FLAG_HYPERLINK
 						return INTERNET_FLAG_HYPERLINK;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_KEEP_CONNECTION"))
 					#ifdef INTERNET_FLAG_KEEP_CONNECTION
 						return INTERNET_FLAG_KEEP_CONNECTION;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_MAKE_PERSISTENT"))
 					#ifdef INTERNET_FLAG_MAKE_PERSISTENT
 						return INTERNET_FLAG_MAKE_PERSISTENT;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_NO_AUTH"))
 					#ifdef INTERNET_FLAG_NO_AUTH
 						return INTERNET_FLAG_NO_AUTH;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_NO_AUTO_REDIRECT"))
 					#ifdef INTERNET_FLAG_NO_AUTO_REDIRECT
 						return INTERNET_FLAG_NO_AUTO_REDIRECT;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_NO_CACHE_WRITE"))
 					#ifdef INTERNET_FLAG_NO_CACHE_WRITE
 						return INTERNET_FLAG_NO_CACHE_WRITE;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_NO_COOKIES"))
 					#ifdef INTERNET_FLAG_NO_COOKIES
 						return INTERNET_FLAG_NO_COOKIES;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_READ_PREFETCH"))
 					#ifdef INTERNET_FLAG_READ_PREFETCH
 						return INTERNET_FLAG_READ_PREFETCH;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_RELOAD"))
 					#ifdef INTERNET_FLAG_RELOAD
 						return INTERNET_FLAG_RELOAD;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_RESYNCHRONIZE"))
 					#ifdef INTERNET_FLAG_RESYNCHRONIZE
 						return INTERNET_FLAG_RESYNCHRONIZE;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_TRANSFER_ASCII"))
 					#ifdef INTERNET_FLAG_TRANSFER_ASCII
 						return INTERNET_FLAG_TRANSFER_ASCII;
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_FLAG_TRANSFER_BINARY"))
 					#ifdef INTERNET_FLAG_TRANSFER_BINARY
 						return INTERNET_FLAG_TRANSFER_BINARY;
@@ -490,7 +478,6 @@
 					#else
 						goto not_there;
 					#endif
-				break;
 				if(strEQ(name, "INTERNET_INVALID_STATUS_CALLBACK"))
 					#ifdef INTERNET_INVALID_STATUS_CALLBACK
 						return (DWORD) INTERNET_INVALID_STATUS_CALLBACK;
@@ -667,7 +654,6 @@
 					#else
 						goto not_there;
 					#endif
-				break;
 				if (strEQ(name, "INTERNET_STATUS_CONNECTING_TO_SERVER"))
 					#ifdef INTERNET_STATUS_CONNECTING_TO_SERVER
 						return INTERNET_STATUS_CONNECTING_TO_SERVER;
diff -ur libwin32-0.16/NetResource/NetResource.xs libwin32-0.171/NetResource/NetResource.xs
--- libwin32-0.16/NetResource/NetResource.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/NetResource/NetResource.xs	Tue Sep 19 16:39:22 2000
@@ -219,14 +219,14 @@
  
 
 BOOL
-EnumerateFunc(SV* ARef, LPNETRESOURCEA lpnr,DWORD dwType) 
-{ 
-    DWORD dwResult, dwResultEnum; 
-    HANDLE hEnum; 
+EnumerateFunc(SV* ARef, LPNETRESOURCEA lpnr,DWORD dwType)
+{
+    DWORD dwResult, dwResultEnum;
+    HANDLE hEnum;
     DWORD cbBuffer = 16384; /* 16K is reasonable size                 */
     DWORD cEntries = 0xFFFFFFFF; /* enumerate all possible entries    */
     LPNETRESOURCEA lpnrLocal;     /* pointer to enumerated structures  */
-    DWORD i; 
+    DWORD i;
     HV*     phvNet;
     SV*        svNetRes;
     AV*	av;
@@ -235,18 +235,19 @@
 	croak("Usage: EnumerateFunc(arrayref,lpresource,type)");
 
     dwResult = WNetOpenEnumA(
-	RESOURCE_GLOBALNET, 
-        dwType, 
-        0,                 /* enumerate all resources                 */ 
-        lpnr,              /* NULL first time this function is called */ 
-        &hEnum);           /* handle to resource                      */ 
+	RESOURCE_GLOBALNET,
+        dwType,
+        0,                 /* enumerate all resources                 */
+        lpnr,              /* NULL first time this function is called */
+        &hEnum);           /* handle to resource                      */
  
-    if (dwResult != NO_ERROR){ 
+    if (dwResult != NO_ERROR){
          dwLastError = dwResult;
-         return FALSE; 
+	 /*PerlIO_printf(Perl_debug_log,"quit1 %ld\n",dwResult);*/
+         return FALSE;
     }
  
-    do { 
+    do {
  
         /* Allocate memory for NETRESOURCE structures. */ 
  
@@ -289,7 +290,10 @@
 		    == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) 
 		{
                     if (!EnumerateFunc(ARef, &lpnrLocal[i], dwType)) {
-			if (dwLastError != ERROR_ACCESS_DENIED) {
+			if (dwLastError != ERROR_ACCESS_DENIED &&
+			    dwLastError != ERROR_BAD_NETPATH &&
+			    dwLastError != ERROR_INVALID_ADDRESS)
+			{
 			    safefree(lpnrLocal);
 			    return FALSE;
 			}
@@ -300,6 +304,7 @@
         else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
 	{ 
             dwLastError = dwResultEnum;
+	    /*PerlIO_printf(Perl_debug_log,"quit2 %ld\n",dwLastError);*/
             safefree(lpnrLocal);
             return(FALSE);
         } 
@@ -310,12 +315,13 @@
  
     if(dwResult != NO_ERROR){
         dwLastError = dwResult;
+	/*PerlIO_printf(Perl_debug_log,"quit3 %ld\n",dwLastError); */
         return FALSE;
     } 
     
     dwLastError = NO_ERROR;
     return TRUE; 
-} 
+}
  
 /*
  * wide character allocation routines used to convert from
diff -ur libwin32-0.16/OLE/Changes libwin32-0.171/OLE/Changes
--- libwin32-0.16/OLE/Changes	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/OLE/Changes	Tue Sep 19 16:39:23 2000
@@ -3,6 +3,19 @@
 Changes in version 0.01-0.03 are by Gurusamy Sarathy. All other changes
 are by Jan Dubois unless attributed otherwise.
 
+0.1401	Mon, September 11th, 2000
+	- fix bug in GetMultiByteEx() sometimes chopping off the last byte
+
+0.14	Tue, August 22th, 2000
+	- remove support for Perl 5.004 & 5.005
+	- don't built for 5.005 Threads (because it won't work anyways)
+	- make sure the other compile options for 5.6 work
+	- support embedded '\0's in BSTR return values
+
+0.1301	Thur, July 13th, 2000 (dougl@ActiveState.com)
+	- patch to fix exported functions
+	- lost UTF-8 support added back in
+
 0.13	Sat, May 6th, 2000
 	- add Win32::OLE::Variant::nothing() function
 	- fix strrev() definition for Borland
diff -ur libwin32-0.16/OLE/OLE.xs libwin32-0.171/OLE/OLE.xs
--- libwin32-0.16/OLE/OLE.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/OLE/OLE.xs	Tue Sep 19 16:39:23 2000
@@ -27,6 +27,8 @@
 
 // #define _DEBUG
 
+#define register /* be gone */
+
 #define MY_VERSION "Win32::OLE(" XS_VERSION ")"
 
 #include <math.h>	/* this hack gets around VC-5.0 brainmelt */
@@ -41,9 +43,7 @@
 #   define DEBUGBREAK
 #endif
 
-#if defined (__cplusplus)
 extern "C" {
-#endif
 
 #ifdef __CYGWIN__
 #   undef WIN32			/* don't use with Cygwin & Perl */
@@ -54,7 +54,7 @@
     char *_strrev(char*);	/* from string.h (msvcrt40) */
 #endif
 
-#define MIN_PERL_DEFINE
+#define PERL_NO_GET_CONTEXT
 #define NO_XSLOCKS
 #include "EXTERN.h"
 #include "perl.h"
@@ -64,36 +64,15 @@
 #undef WORD
 typedef unsigned short WORD;
 
-#if (PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 1))
-#   error Win32::OLE module requires Perl 5.004_01 or later
-#endif
-
-#if (PATCHLEVEL < 5)
-#   ifndef PL_dowarn
-#	define PL_dowarn	dowarn
-#	define PL_sv_undef	sv_undef
-#	define PL_sv_yes	sv_yes
-#	define PL_sv_no		sv_no
-#   endif
-#   define PL_hints		hints
-#   define PL_modglobal		modglobal
-#endif
-
-#ifndef CPERLarg
-#   define CPERLarg
-#   define CPERLarg_
-#   define PERL_OBJECT_THIS
-#   define PERL_OBJECT_THIS_
+#if PATCHLEVEL < 6
+#   error Win32::OLE requires Perl 5.6.0 or later
 #endif
 
-#ifndef pTHX_
-#   define pTHX_
+#ifdef USE_5005THREADS
+#   error Win32::OLE is incompatible with 5.005 style threads
 #endif
 
-#undef THIS_
-#define THIS_ PERL_OBJECT_THIS_
-
-#if !defined(_DEBUG)
+#ifndef _DEBUG
 #   define DBG(a)
 #else
 #   define DBG(a)  MyDebug a
@@ -182,22 +161,14 @@
 
 }   PERINTERP;
 
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
-#   if (PATCHLEVEL == 4) && (SUBVERSION < 68)
-#       define dPERINTERP                                                 \
-           SV *interp = perl_get_sv(MY_VERSION, FALSE);                   \
-           if (!interp || !SvIOK(interp))	                          \
-               warn(MY_VERSION ": Per-interpreter data not initialized"); \
-           PERINTERP *pInterp = (PERINTERP*)SvIV(interp)
-#   else
-#	define dPERINTERP                                                 \
-           SV **pinterp = hv_fetch(PL_modglobal, MY_VERSION,              \
-                                   sizeof(MY_VERSION)-1, FALSE);          \
-           if (!pinterp || !*pinterp || !SvIOK(*pinterp))		  \
-               warn(MY_VERSION ": Per-interpreter data not initialized"); \
-	   PERINTERP *pInterp = (PERINTERP*)SvIV(*pinterp)
-#   endif
-#   define INTERP pInterp
+#ifdef PERL_IMPLICIT_CONTEXT
+#    define dPERINTERP                                                 \
+        SV **pinterp = hv_fetch(PL_modglobal, MY_VERSION,              \
+                                sizeof(MY_VERSION)-1, FALSE);          \
+        if (!pinterp || !*pinterp || !SvIOK(*pinterp))		       \
+            warn(MY_VERSION ": Per-interpreter data not initialized"); \
+        PERINTERP *pInterp = (PERINTERP*)SvIV(*pinterp)
+#    define INTERP pInterp
 #else
 static PERINTERP Interp;
 #   define dPERINTERP extern int errno
@@ -223,7 +194,7 @@
     long lMagic;
     OBJECTHEADER *pNext;
     OBJECTHEADER *pPrevious;
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
+#ifdef PERL_IMPLICIT_CONTEXT
     PERINTERP    *pInterp;
 #endif
 }   OBJECTHEADER;
@@ -323,35 +294,7 @@
       EXCEPINFO *pexcepinfo,
       UINT *puArgErr);
 
-#ifdef _DEBUG
-    STDMETHOD(Dummy1)();
-    STDMETHOD(Dummy2)();
-    STDMETHOD(Dummy3)();
-    STDMETHOD(Dummy4)();
-    STDMETHOD(Dummy5)();
-    STDMETHOD(Dummy6)();
-    STDMETHOD(Dummy7)();
-    STDMETHOD(Dummy8)();
-    STDMETHOD(Dummy9)();
-    STDMETHOD(Dummy10)();
-    STDMETHOD(Dummy11)();
-    STDMETHOD(Dummy12)();
-    STDMETHOD(Dummy13)();
-    STDMETHOD(Dummy14)();
-    STDMETHOD(Dummy15)();
-    STDMETHOD(Dummy16)();
-    STDMETHOD(Dummy17)();
-    STDMETHOD(Dummy18)();
-    STDMETHOD(Dummy19)();
-    STDMETHOD(Dummy20)();
-    STDMETHOD(Dummy21)();
-    STDMETHOD(Dummy22)();
-    STDMETHOD(Dummy23)();
-    STDMETHOD(Dummy24)();
-    STDMETHOD(Dummy25)();
-#endif
-
-    EventSink(CPERLarg_ WINOLEOBJECT *pObj, SV *events,
+    EventSink(pTHX_ WINOLEOBJECT *pObj, SV *events,
 	      REFIID riid, ITypeInfo *pTypeInfo);
     ~EventSink(void);
     HRESULT Advise(IConnectionPoint *pConnectionPoint);
@@ -366,8 +309,8 @@
     SV *m_events;
     IID m_iid;
     ITypeInfo *m_pTypeInfo;
-#ifdef PERL_OBJECT
-    CPERLproto m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX;
 #endif
 };
 
@@ -402,69 +345,26 @@
       EXCEPINFO *pexcepinfo,
       UINT *puArgErr);
 
-    Forwarder(CPERLarg_ HV *stash, SV *method);
+    Forwarder(pTHX_ HV *stash, SV *method);
     ~Forwarder(void);
 
  private:
     int m_refcount;
     HV *m_stash;
     SV *m_method;
-#ifdef PERL_OBJECT
-    CPERLproto m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX;
 #endif
 };
 
 /* forward declarations */
-HRESULT SetSVFromVariantEx(CPERLarg_ VARIANTARG *pVariant, SV* sv, HV *stash,
+HRESULT SetSVFromVariantEx(pTHX_ VARIANTARG *pVariant, SV* sv, HV *stash,
 			   BOOL bByRefObj=FALSE);
-HRESULT SetVariantFromSVEx(CPERLarg_ SV* sv, VARIANT *pVariant, UINT cp,
+HRESULT SetVariantFromSVEx(pTHX_ SV* sv, VARIANT *pVariant, UINT cp,
 			   LCID lcid);
-HRESULT AssignVariantFromSV(CPERLarg_ SV* sv, VARIANT *pVariant,
+HRESULT AssignVariantFromSV(pTHX_ SV* sv, VARIANT *pVariant,
 			    UINT cp, LCID lcid);
 
-/* The following function from IO.xs is in the core starting with 5.004_63 */
-#if (PATCHLEVEL == 4) && (SUBVERSION < 63)
-void
-newCONSTSUB(HV *stash, char *name, SV *sv)
-{
-#ifdef dTHR
-    dTHR;
-#endif
-    U32 oldhints = PL_hints;
-    HV *old_cop_stash = curcop->cop_stash;
-    HV *old_curstash = curstash;
-    line_t oldline = curcop->cop_line;
-    curcop->cop_line = copline;
-
-    PL_hints &= ~HINT_BLOCK_SCOPE;
-    if(stash)
-	curstash = curcop->cop_stash = stash;
-
-    newSUB(
-	start_subparse(FALSE, 0),
-	newSVOP(OP_CONST, 0, newSVpv(name,0)),
-	newSVOP(OP_CONST, 0, &sv_no),	/* SvPV(&sv_no) == "" -- GMB */
-	newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
-    );
-
-    PL_hints = oldhints;
-    curcop->cop_stash = old_cop_stash;
-    curstash = old_curstash;
-    curcop->cop_line = oldline;
-}
-#endif
-
-/* SvPV_nolen() macro first defined in 5.005_55 */
-#if (PATCHLEVEL == 4) || ((PATCHLEVEL == 5) && (SUBVERSION < 55))
-char *
-MySvPVX(CPERLarg_ SV *sv)
-{
-    STRLEN n_a;
-    return SvPV(sv, n_a);
-}
-#    define SvPV_nolen(sv) (SvPOK(sv) ? (SvPVX(sv)) : MySvPVX(THIS_ sv))
-#endif
-
 //------------------------------------------------------------------------
 
 inline void
@@ -481,7 +381,7 @@
 }   /* SpinMessageLoop */
 
 BOOL
-IsLocalMachine(CPERLarg_ char *pszMachine)
+IsLocalMachine(pTHX_ char *pszMachine)
 {
     char szComputerName[MAX_COMPUTERNAME_LENGTH+1];
     DWORD dwSize = sizeof(szComputerName);
@@ -494,9 +394,19 @@
 	return TRUE;
 
     /* Check against local computer name (from registry) */
-    if (GetComputerName(szComputerName, &dwSize)
-	&& stricmp(pszName, szComputerName) == 0)
-	return TRUE;
+    if (USING_WIDE()) {
+	WCHAR wComputerName[MAX_COMPUTERNAME_LENGTH+1];
+	WCHAR wHostName[MAX_COMPUTERNAME_LENGTH+1];
+	A2WHELPER(pszName, wHostName, sizeof(wHostName));
+	if (GetComputerNameW(wComputerName, &dwSize)
+	    && _wcsicmp(wHostName, wComputerName) == 0)
+	    return TRUE;
+    }
+    else {
+	if (GetComputerNameA(szComputerName, &dwSize)
+	    && stricmp(pszName, szComputerName) == 0)
+	    return TRUE;
+    }
 
     /* gethostname(), gethostbyname() and inet_addr() all call proxy functions
      * in the Perl socket layer wrapper in win32sck.c. Therefore calling
@@ -563,14 +473,21 @@
 }   /* IsLocalMachine */
 
 HRESULT
-CLSIDFromRemoteRegistry(CPERLarg_ char *pszHost, char *pszProgID, CLSID *pCLSID)
+CLSIDFromRemoteRegistry(pTHX_ char *pszHost, char *pszProgID, CLSID *pCLSID)
 {
     HKEY hKeyLocalMachine;
     HKEY hKeyProgID;
     LONG err;
+    WCHAR wbuffer[MAX_PATH+1];
     HRESULT hr = S_OK;
 
-    err = RegConnectRegistry(pszHost, HKEY_LOCAL_MACHINE, &hKeyLocalMachine);
+    if (USING_WIDE()) {
+	A2WHELPER(pszHost, wbuffer, sizeof(wbuffer));
+	err = RegConnectRegistryW(wbuffer, HKEY_LOCAL_MACHINE, &hKeyLocalMachine);
+    }
+    else {
+	err = RegConnectRegistryA(pszHost, HKEY_LOCAL_MACHINE, &hKeyLocalMachine);
+    }
     if (err != ERROR_SUCCESS)
 	return HRESULT_FROM_WIN32(err);
 
@@ -578,8 +495,15 @@
     sv_catpv(subkey, pszProgID);
     sv_catpv(subkey, "\\CLSID");
 
-    err = RegOpenKeyEx(hKeyLocalMachine, SvPV_nolen(subkey), 0, KEY_READ,
-		       &hKeyProgID);
+    if (USING_WIDE()) {
+	A2WHELPER(SvPV_nolen(subkey), wbuffer, sizeof(wbuffer));
+	err = RegOpenKeyExW(hKeyLocalMachine, wbuffer, 0, KEY_READ,
+			   &hKeyProgID);
+    }
+    else {
+	err = RegOpenKeyExA(hKeyLocalMachine, SvPV_nolen(subkey), 0, KEY_READ,
+			   &hKeyProgID);
+    }
     if (err != ERROR_SUCCESS)
 	hr = HRESULT_FROM_WIN32(err);
     else {
@@ -617,64 +541,81 @@
  * The caller must free this buffer using the ReleaseBuffer function. */
 
 inline void
-ReleaseBuffer(CPERLarg_ void *pszHeap, void *pszStack)
+ReleaseBuffer(pTHX_ void *pszHeap, void *pszStack)
 {
     if (pszHeap != pszStack && pszHeap)
 	Safefree(pszHeap);
 }
 
 char *
-GetMultiByte(CPERLarg_ OLECHAR *wide, char *psz, int len, UINT cp)
+GetMultiByteEx(pTHX_ OLECHAR *wide, int *pcch, char *psz, int len, UINT cp)
 {
     int count;
 
     if (psz) {
-	if (!wide) {
-	    *psz = (char) 0;
+	if (!wide || !*pcch) {
+ fail:
+	    *psz = (char)0;
+            *pcch = 0;
 	    return psz;
 	}
-	count = WideCharToMultiByte(cp, 0, wide, -1, psz, len, NULL, NULL);
+	count = WideCharToMultiByte(cp, 0, wide, *pcch, psz, len, NULL, NULL);
 	if (count > 0)
-	    return psz;
+            goto succeed;
     }
-    else if (!wide) {
+    else if (!wide || !*pcch) {
 	Newz(0, psz, 1, char);
+        *pcch = 0;
 	return psz;
     }
 
-    count = WideCharToMultiByte(cp, 0, wide, -1, NULL, 0, NULL, NULL);
+    count = WideCharToMultiByte(cp, 0, wide, *pcch, NULL, 0, NULL, NULL);
     if (count == 0) { /* should never happen */
 	warn(MY_VERSION ": GetMultiByte() failure: %lu", GetLastError());
 	DEBUGBREAK;
 	if (!psz)
 	    New(0, psz, 1, char);
-	*psz = (char) 0;
-	return psz;
+        goto fail;
     }
 
     Newz(0, psz, count, char);
-    WideCharToMultiByte(cp, 0, wide, -1, psz, count, NULL, NULL);
+    WideCharToMultiByte(cp, 0, wide, *pcch, psz, count, NULL, NULL);
+
+ succeed:
+    if (*pcch == -1)
+        *pcch = count - 1; /* because count includes the trailing '\0' */
+    else
+        *pcch = count;
     return psz;
 
-}   /* GetMultiByte */
+}   /* GetMultiByteEx */
+
+char *
+GetMultiByte(pTHX_ OLECHAR *wide, char *psz, int len, UINT cp)
+{
+    int cch = -1;
+    return GetMultiByteEx(aTHX_ wide, &cch, psz, len, cp);
+}
 
 SV *
-sv_setwide(CPERLarg_ SV *sv, OLECHAR *wide, UINT cp)
+sv_setbstr(pTHX_ SV *sv, BSTR bstr, UINT cp)
 {
     char szBuffer[OLE_BUF_SIZ];
     char *pszBuffer;
+    int len = SysStringLen(bstr);
 
-    pszBuffer = GetMultiByte(THIS_ wide, szBuffer, sizeof(szBuffer), cp);
+    pszBuffer = GetMultiByteEx(aTHX_ bstr, &len,
+                               szBuffer, sizeof(szBuffer), cp);
     if (!sv)
-	sv = newSVpv(pszBuffer, 0);
+	sv = newSVpvn(pszBuffer, len);
     else
-	sv_setpv(sv, pszBuffer);
-    ReleaseBuffer(THIS_ pszBuffer, szBuffer);
+	sv_setpvn(sv, pszBuffer, len);
+    ReleaseBuffer(aTHX_ pszBuffer, szBuffer);
     return sv;
 }
 
 OLECHAR *
-GetWideChar(CPERLarg_ char *psz, OLECHAR *wide, int len, UINT cp)
+GetWideChar(pTHX_ char *psz, OLECHAR *wide, int len, UINT cp)
 {
     /* Note: len is number of OLECHARs, not bytes! */
     int count;
@@ -710,7 +651,7 @@
 }   /* GetWideChar */
 
 HV *
-GetStash(CPERLarg_ SV *sv)
+GetStash(pTHX_ SV *sv)
 {
     if (sv_isobject(sv))
 	return SvSTASH(SvRV(sv));
@@ -722,7 +663,7 @@
 }   /* GetStash */
 
 HV *
-GetWin32OleStash(CPERLarg_ SV *sv)
+GetWin32OleStash(pTHX_ SV *sv)
 {
     SV *pkg;
 
@@ -749,7 +690,7 @@
 }   /* GetWin32OleStash */
 
 IV
-QueryPkgVar(CPERLarg_ HV *stash, char *var, STRLEN len, IV def=0)
+QueryPkgVar(pTHX_ HV *stash, char *var, STRLEN len, IV def=0)
 {
     SV *sv;
     GV **gv = (GV**)hv_fetch(stash, var, len, FALSE);
@@ -764,7 +705,7 @@
 }
 
 void
-SetLastOleError(CPERLarg_ HV *stash, HRESULT hr=S_OK, char *pszMsg=NULL)
+SetLastOleError(pTHX_ HV *stash, HRESULT hr=S_OK, char *pszMsg=NULL)
 {
     /* Find $Win32::OLE::LastError */
     SV *sv = sv_2mortal(newSVpv(HvNAME(stash), 0));
@@ -786,13 +727,13 @@
 }
 
 void
-ReportOleError(CPERLarg_ HV *stash, HRESULT hr, EXCEPINFO *pExcep=NULL,
+ReportOleError(pTHX_ HV *stash, HRESULT hr, EXCEPINFO *pExcep=NULL,
 	       SV *svAdd=NULL)
 {
     dSP;
 
     SV *sv;
-    IV warnlvl = QueryPkgVar(THIS_ stash, WARN_NAME, WARN_LEN);
+    IV warnlvl = QueryPkgVar(aTHX_ stash, WARN_NAME, WARN_LEN);
     GV **pgv = (GV**)hv_fetch(stash, WARN_NAME, WARN_LEN, FALSE);
     CV *cv = Nullcv;
 
@@ -810,20 +751,20 @@
 	char *pszSource = szSource;
 	char *pszDesc = szDesc;
 
-	UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+	UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 	if (pExcep->bstrSource)
-	    pszSource = GetMultiByte(THIS_ pExcep->bstrSource,
+	    pszSource = GetMultiByte(aTHX_ pExcep->bstrSource,
 				     szSource, sizeof(szSource), cp);
 
 	if (pExcep->bstrDescription)
-	    pszDesc = GetMultiByte(THIS_ pExcep->bstrDescription,
+	    pszDesc = GetMultiByte(aTHX_ pExcep->bstrDescription,
 				   szDesc, sizeof(szDesc), cp);
 
 	sv_setpvf(sv, "OLE exception from \"%s\":\n\n%s\n\n",
 		  pszSource, pszDesc);
 
-	ReleaseBuffer(THIS_ pszSource, szSource);
-	ReleaseBuffer(THIS_ pszDesc, szDesc);
+	ReleaseBuffer(aTHX_ pszSource, szSource);
+	ReleaseBuffer(aTHX_ pszDesc, szDesc);
 	/* SysFreeString accepts NULL too */
 	SysFreeString(pExcep->bstrSource);
 	SysFreeString(pExcep->bstrDescription);
@@ -835,11 +776,30 @@
 
     /* try to append ': "error text"' from message catalog */
     char *pszMsgText;
-    DWORD dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+    DWORD dwCount;
+    if (USING_WIDE()) {
+	WCHAR *wzMsgText;
+	dwCount = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+				  FORMAT_MESSAGE_FROM_SYSTEM |
+				  FORMAT_MESSAGE_IGNORE_INSERTS,
+				  NULL, hr, lcidSystemDefault,
+				  (LPWSTR)&wzMsgText, 0, NULL);
+	pszMsgText = (LPSTR)LocalAlloc(0, (dwCount+1)*2);
+	if(pszMsgText) {
+	    W2AHELPER(wzMsgText, pszMsgText, (dwCount+1)*2);
+	    dwCount = strlen(pszMsgText);
+	}
+	else
+	    dwCount = 0;
+	LocalFree(wzMsgText);
+    }
+    else {
+	dwCount = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
 				  FORMAT_MESSAGE_FROM_SYSTEM |
 				  FORMAT_MESSAGE_IGNORE_INSERTS,
 				  NULL, hr, lcidSystemDefault,
-				  (LPTSTR)&pszMsgText, 0, NULL);
+				  (LPSTR)&pszMsgText, 0, NULL);
+    }
     if (dwCount > 0) {
 	sv_catpv(sv, ": \"");
 	/* remove trailing dots and CRs/LFs from message */
@@ -886,7 +846,7 @@
 	}
     }
 
-    SetLastOleError(THIS_ stash, hr, SvPVX(sv));
+    SetLastOleError(aTHX_ stash, hr, SvPVX(sv));
 
     DBG(("ReportOleError: hr=0x%08x warnlvl=%d\n%s", hr, warnlvl, SvPVX(sv)));
 
@@ -913,18 +873,18 @@
 }   /* ReportOleError */
 
 inline BOOL
-CheckOleError(CPERLarg_ HV *stash, HRESULT hr, EXCEPINFO *pExcep=NULL,
+CheckOleError(pTHX_ HV *stash, HRESULT hr, EXCEPINFO *pExcep=NULL,
 	      SV *svAdd=NULL)
 {
     if (FAILED(hr)) {
-	ReportOleError(THIS_ stash, hr, pExcep, svAdd);
+	ReportOleError(aTHX_ stash, hr, pExcep, svAdd);
 	return TRUE;
     }
     return FALSE;
 }
 
 SV *
-CheckDestroyFunction(CPERLarg_ SV *sv, char *szMethod)
+CheckDestroyFunction(pTHX_ SV *sv, char *szMethod)
 {
     /* undef */
     if (!SvOK(sv))
@@ -940,7 +900,7 @@
 }
 
 void
-AddToObjectChain(CPERLarg_ OBJECTHEADER *pHeader, long lMagic)
+AddToObjectChain(pTHX_ OBJECTHEADER *pHeader, long lMagic)
 {
     dPERINTERP;
     DBG(("AddToObjectChain(0x%08x) lMagic=0x%08x", pHeader, lMagic));
@@ -950,7 +910,7 @@
     pHeader->pPrevious = NULL;
     pHeader->pNext = g_pObj;
 
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
+#ifdef PERL_IMPLICIT_CONTEXT
     pHeader->pInterp = INTERP;
 #endif
 
@@ -961,7 +921,7 @@
 }
 
 void
-RemoveFromObjectChain(CPERLarg_ OBJECTHEADER *pHeader)
+RemoveFromObjectChain(pTHX_ OBJECTHEADER *pHeader)
 {
     DBG(("RemoveFromObjectChain(0x%08x) lMagic=0x%08x\n", pHeader,
 	 pHeader ? pHeader->lMagic : 0));
@@ -969,7 +929,7 @@
     if (!pHeader)
 	return;
 
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
+#ifdef PERL_IMPLICIT_CONTEXT
     PERINTERP *pInterp = pHeader->pInterp;
 #endif
 
@@ -990,13 +950,13 @@
 }
 
 SV *
-CreatePerlObject(CPERLarg_ HV *stash, IDispatch *pDispatch, SV *destroy)
+CreatePerlObject(pTHX_ HV *stash, IDispatch *pDispatch, SV *destroy)
 {
     dPERINTERP;
 
     /* returns a mortal reference to a new Perl OLE object */
 
-    IV unique = QueryPkgVar(THIS_ stash, _UNIQUE_NAME, _UNIQUE_LEN);
+    IV unique = QueryPkgVar(aTHX_ stash, _UNIQUE_NAME, _UNIQUE_LEN);
     if (unique) {
         IUnknown *punk; // XXX check error?
         pDispatch->QueryInterface(IID_IUnknown, (void**)&punk);
@@ -1051,7 +1011,7 @@
         pObj->flags |= OBJFLAG_UNIQUE;
     }
 
-    AddToObjectChain(THIS_ &pObj->header, WINOLE_MAGIC);
+    AddToObjectChain(aTHX_ &pObj->header, WINOLE_MAGIC);
 
     DBG(("CreatePerlObject=|%lx| Class=%s Tie=%s pDispatch=0x%x\n", pObj,
 	 HvNAME(stash), szTie, pDispatch));
@@ -1066,7 +1026,7 @@
 }   /* CreatePerlObject */
 
 void
-ReleasePerlObject(CPERLarg_ WINOLEOBJECT *pObj)
+ReleasePerlObject(pTHX_ WINOLEOBJECT *pObj)
 {
     dSP;
     HV *stash = SvSTASH(pObj->self);
@@ -1164,7 +1124,7 @@
 }   /* ReleasePerlObject */
 
 WINOLEOBJECT *
-GetOleObject(CPERLarg_ SV *sv, BOOL bDESTROY=FALSE)
+GetOleObject(pTHX_ SV *sv, BOOL bDESTROY=FALSE)
 {
     if (sv_isobject(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV) {
 	SV **psv = hv_fetch((HV*)SvRV(sv), PERL_OLE_ID, PERL_OLE_IDLEN, 0);
@@ -1173,14 +1133,10 @@
 	if (!psv && bDESTROY)
 	    return NULL;
 
-#if (PATCHLEVEL > 4) || ((PATCHLEVEL == 4) && (SUBVERSION > 4))
 	if (psv && SvGMAGICAL(*psv))
 	    mg_get(*psv);
 
 	if (psv && SvIOK(*psv)) {
-#else
-	if (psv) {
-#endif
 	    WINOLEOBJECT *pObj = (WINOLEOBJECT*)SvIV(*psv);
 
 	    DBG(("GetOleObject = |%lx|\n", pObj));
@@ -1195,7 +1151,7 @@
 }
 
 WINOLEENUMOBJECT *
-GetOleEnumObject(CPERLarg_ SV *sv, BOOL bDESTROY=FALSE)
+GetOleEnumObject(pTHX_ SV *sv, BOOL bDESTROY=FALSE)
 {
     if (sv_isobject(sv) && sv_derived_from(sv, szWINOLEENUM)) {
 	WINOLEENUMOBJECT *pEnumObj = (WINOLEENUMOBJECT*)SvIV(SvRV(sv));
@@ -1210,7 +1166,7 @@
 }
 
 WINOLEVARIANTOBJECT *
-GetOleVariantObject(CPERLarg_ SV *sv, BOOL bWarn=TRUE)
+GetOleVariantObject(pTHX_ SV *sv, BOOL bWarn=TRUE)
 {
     if (sv_isobject(sv) && sv_derived_from(sv, szWINOLEVARIANT)) {
 	WINOLEVARIANTOBJECT *pVarObj = (WINOLEVARIANTOBJECT*)SvIV(SvRV(sv));
@@ -1227,7 +1183,7 @@
 }
 
 SV *
-CreateTypeLibObject(CPERLarg_ ITypeLib *pTypeLib, TLIBATTR *pTLibAttr)
+CreateTypeLibObject(pTHX_ ITypeLib *pTypeLib, TLIBATTR *pTLibAttr)
 {
     WINOLETYPELIBOBJECT *pObj;
     New(0, pObj, 1, WINOLETYPELIBOBJECT);
@@ -1235,14 +1191,14 @@
     pObj->pTypeLib = pTypeLib;
     pObj->pTLibAttr = pTLibAttr;
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pObj, WINOLETYPELIB_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pObj, WINOLETYPELIB_MAGIC);
 
     return sv_bless(newRV_noinc(newSViv((IV)pObj)),
 		    gv_stashpv(szWINOLETYPELIB, TRUE));
 }
 
 WINOLETYPELIBOBJECT *
-GetOleTypeLibObject(CPERLarg_ SV *sv)
+GetOleTypeLibObject(pTHX_ SV *sv)
 {
     if (sv_isobject(sv) && sv_derived_from(sv, szWINOLETYPELIB)) {
 	WINOLETYPELIBOBJECT *pObj = (WINOLETYPELIBOBJECT*)SvIV(SvRV(sv));
@@ -1256,7 +1212,7 @@
 }
 
 SV *
-CreateTypeInfoObject(CPERLarg_ ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr)
+CreateTypeInfoObject(pTHX_ ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr)
 {
     WINOLETYPEINFOOBJECT *pObj;
     New(0, pObj, 1, WINOLETYPEINFOOBJECT);
@@ -1264,14 +1220,14 @@
     pObj->pTypeInfo = pTypeInfo;
     pObj->pTypeAttr = pTypeAttr;
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pObj, WINOLETYPEINFO_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pObj, WINOLETYPEINFO_MAGIC);
 
     return sv_bless(newRV_noinc(newSViv((IV)pObj)),
 		    gv_stashpv(szWINOLETYPEINFO, TRUE));
 }
 
 WINOLETYPEINFOOBJECT *
-GetOleTypeInfoObject(CPERLarg_ SV *sv)
+GetOleTypeInfoObject(pTHX_ SV *sv)
 {
     if (sv_isobject(sv) && sv_derived_from(sv, szWINOLETYPEINFO)) {
 	WINOLETYPEINFOOBJECT *pObj = (WINOLETYPEINFOOBJECT*)SvIV(SvRV(sv));
@@ -1286,7 +1242,7 @@
 }
 
 BSTR
-AllocOleString(CPERLarg_ char* pStr, int length, UINT cp)
+AllocOleString(pTHX_ char* pStr, int length, UINT cp)
 {
     int count = MultiByteToWideChar(cp, 0, pStr, length, NULL, 0);
     BSTR bstr = SysAllocStringLen(NULL, count);
@@ -1295,7 +1251,7 @@
 }
 
 HRESULT
-GetHashedDispID(CPERLarg_ WINOLEOBJECT *pObj, char *buffer, STRLEN len,
+GetHashedDispID(pTHX_ WINOLEOBJECT *pObj, char *buffer, STRLEN len,
 		DISPID &dispID, LCID lcid, UINT cp)
 {
     HRESULT hr;
@@ -1316,9 +1272,9 @@
     OLECHAR Buffer[OLE_BUF_SIZ];
     OLECHAR *pBuffer;
 
-    pBuffer = GetWideChar(THIS_ buffer, Buffer, OLE_BUF_SIZ, cp);
+    pBuffer = GetWideChar(aTHX_ buffer, Buffer, OLE_BUF_SIZ, cp);
     hr = pObj->pDispatch->GetIDsOfNames(IID_NULL, &pBuffer, 1, lcid, &id);
-    ReleaseBuffer(THIS_ pBuffer, Buffer);
+    ReleaseBuffer(aTHX_ pBuffer, Buffer);
     /* Don't call CheckOleError! Caller might retry the "unnamed" method */
     if (SUCCEEDED(hr)) {
 	hv_store(pObj->hashTable, buffer, len, newSViv(id), 0);
@@ -1329,7 +1285,7 @@
 }   /* GetHashedDispID */
 
 void
-FetchTypeInfo(CPERLarg_ WINOLEOBJECT *pObj)
+FetchTypeInfo(pTHX_ WINOLEOBJECT *pObj)
 {
     unsigned int count;
     ITypeInfo *pTypeInfo;
@@ -1345,21 +1301,21 @@
 	return;
     }
 
-    if (CheckOleError(THIS_ stash, hr)) {
+    if (CheckOleError(aTHX_ stash, hr)) {
 	warn(MY_VERSION ": FetchTypeInfo() GetTypeInfoCount failed");
 	DEBUGBREAK;
 	return;
     }
 
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
     hr = pObj->pDispatch->GetTypeInfo(0, lcid, &pTypeInfo);
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	return;
 
     hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	return;
     }
 
@@ -1400,7 +1356,7 @@
 
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	return;
     }
 
@@ -1420,7 +1376,7 @@
 }   /* FetchTypeInfo */
 
 SV *
-NextPropertyName(CPERLarg_ WINOLEOBJECT *pObj)
+NextPropertyName(pTHX_ WINOLEOBJECT *pObj)
 {
     HRESULT hr;
     unsigned int cName;
@@ -1430,8 +1386,8 @@
 	return &PL_sv_undef;
 
     HV *stash = SvSTASH(pObj->self);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
-    int newenum = QueryPkgVar(THIS_ stash, _NEWENUM_NAME, _NEWENUM_LEN);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
+    int newenum = QueryPkgVar(aTHX_ stash, _NEWENUM_NAME, _NEWENUM_LEN);
 
     while (pObj->PropIndex < pObj->cFuncs+pObj->cVars) {
 	ULONG index = pObj->PropIndex++;
@@ -1440,7 +1396,7 @@
 	    FUNCDESC *pFuncDesc;
 
 	    hr = pObj->pTypeInfo->GetFuncDesc(index, &pFuncDesc);
-	    if (CheckOleError(THIS_ stash, hr))
+	    if (CheckOleError(aTHX_ stash, hr))
 		continue;
 
             if (newenum && pFuncDesc->memid == DISPID_NEWENUM)
@@ -1458,10 +1414,10 @@
 
 	    hr = pObj->pTypeInfo->GetNames(pFuncDesc->memid, &bstr, 1, &cName);
 	    pObj->pTypeInfo->ReleaseFuncDesc(pFuncDesc);
-	    if (CheckOleError(THIS_ stash, hr) || cName == 0 || !bstr)
+	    if (CheckOleError(aTHX_ stash, hr) || cName == 0 || !bstr)
 		continue;
 
-	    SV *sv = sv_setwide(THIS_ NULL, bstr, cp);
+	    SV *sv = sv_setbstr(aTHX_ NULL, bstr, cp);
 	    SysFreeString(bstr);
 	    return sv;
 	}
@@ -1471,7 +1427,7 @@
 
 	    index -= pObj->cFuncs;
 	    hr = pObj->pTypeInfo->GetVarDesc(index, &pVarDesc);
-	    if (CheckOleError(THIS_ stash, hr))
+	    if (CheckOleError(aTHX_ stash, hr))
 		continue;
 
 	    if (!(pVarDesc->varkind & VAR_DISPATCH) ||
@@ -1485,10 +1441,10 @@
 
 	    hr = pObj->pTypeInfo->GetNames(pVarDesc->memid, &bstr, 1, &cName);
 	    pObj->pTypeInfo->ReleaseVarDesc(pVarDesc);
-	    if (CheckOleError(THIS_ stash, hr) || cName == 0 || !bstr)
+	    if (CheckOleError(aTHX_ stash, hr) || cName == 0 || !bstr)
 		continue;
 
-	    SV *sv = sv_setwide(THIS_ NULL, bstr, cp);
+	    SV *sv = sv_setbstr(aTHX_ NULL, bstr, cp);
 	    SysFreeString(bstr);
 	    return sv;
 	}
@@ -1498,7 +1454,7 @@
 }   /* NextPropertyName */
 
 HV *
-GetDocumentation(CPERLarg_ BSTR bstrName, BSTR bstrDocString,
+GetDocumentation(pTHX_ BSTR bstrName, BSTR bstrDocString,
 		 DWORD dwHelpContext, BSTR bstrHelpFile)
 {
     HV *hv = newHV();
@@ -1507,19 +1463,19 @@
     // XXX use correct codepage ???
     UINT cp = CP_ACP;
 
-    pszStr = GetMultiByte(THIS_ bstrName, szStr, sizeof(szStr), cp);
+    pszStr = GetMultiByte(aTHX_ bstrName, szStr, sizeof(szStr), cp);
     hv_store(hv, "Name", 4, newSVpv(pszStr, 0), 0);
-    ReleaseBuffer(THIS_ pszStr, szStr);
+    ReleaseBuffer(aTHX_ pszStr, szStr);
     SysFreeString(bstrName);
 
-    pszStr = GetMultiByte(THIS_ bstrDocString, szStr, sizeof(szStr), cp);
+    pszStr = GetMultiByte(aTHX_ bstrDocString, szStr, sizeof(szStr), cp);
     hv_store(hv, "DocString", 9, newSVpv(pszStr, 0), 0);
-    ReleaseBuffer(THIS_ pszStr, szStr);
+    ReleaseBuffer(aTHX_ pszStr, szStr);
     SysFreeString(bstrDocString);
 
-    pszStr = GetMultiByte(THIS_ bstrHelpFile, szStr, sizeof(szStr), cp);
+    pszStr = GetMultiByte(aTHX_ bstrHelpFile, szStr, sizeof(szStr), cp);
     hv_store(hv, "HelpFile", 8, newSVpv(pszStr, 0), 0);
-    ReleaseBuffer(THIS_ pszStr, szStr);
+    ReleaseBuffer(aTHX_ pszStr, szStr);
     SysFreeString(bstrHelpFile);
 
     hv_store(hv, "HelpContext", 11, newSViv(dwHelpContext), 0);
@@ -1529,7 +1485,7 @@
 }   /* GetDocumentation */
 
 HRESULT
-TranslateTypeDesc(CPERLarg_ TYPEDESC *pTypeDesc, WINOLETYPEINFOOBJECT *pObj,
+TranslateTypeDesc(pTHX_ TYPEDESC *pTypeDesc, WINOLETYPEINFOOBJECT *pObj,
 		  AV *av)
 {
     HRESULT hr = S_OK;
@@ -1542,7 +1498,7 @@
 	if (SUCCEEDED(hr)) {
 	    hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
 	    if (SUCCEEDED(hr))
-		sv = CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr);
+		sv = CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr);
 	    else
 		pTypeInfo->Release();
 	}
@@ -1560,19 +1516,19 @@
     av_push(av, sv);
 
     if (pTypeDesc->vt == VT_PTR || pTypeDesc->vt == VT_SAFEARRAY)
-	hr = TranslateTypeDesc(THIS_ pTypeDesc->lptdesc, pObj, av);
+	hr = TranslateTypeDesc(aTHX_ pTypeDesc->lptdesc, pObj, av);
 
     return hr;
 }
 
 HV *
-TranslateElemDesc(CPERLarg_ ELEMDESC *pElemDesc, WINOLETYPEINFOOBJECT *pObj,
+TranslateElemDesc(pTHX_ ELEMDESC *pElemDesc, WINOLETYPEINFOOBJECT *pObj,
 		  HV *olestash)
 {
     HV *hv = newHV();
 
     AV *av = newAV();
-    TranslateTypeDesc(THIS_  &pElemDesc->tdesc, pObj, av);
+    TranslateTypeDesc(aTHX_  &pElemDesc->tdesc, pObj, av);
     hv_store(hv, "vt", 2, newRV_noinc((SV*)av), 0);
 
     USHORT wParamFlags = pElemDesc->paramdesc.wParamFlags;
@@ -1585,7 +1541,7 @@
 	// XXX should be stored as a Win32::OLE::Variant object ?
 	SV *sv = newSV(0);
 	// XXX check return code
-	SetSVFromVariantEx(THIS_ &pParamDescEx->varDefaultValue,
+	SetSVFromVariantEx(aTHX_ &pParamDescEx->varDefaultValue,
 			   sv, olestash);
 	hv_store(hv, "varDefaultValue", 15, sv, 0);
     }
@@ -1595,7 +1551,7 @@
 }   /* TranslateElemDesc */
 
 HRESULT
-FindIID(CPERLarg_ WINOLEOBJECT *pObj, char *pszItf, IID *piid,
+FindIID(pTHX_ WINOLEOBJECT *pObj, char *pszItf, IID *piid,
 	ITypeInfo **ppTypeInfo, UINT cp, LCID lcid)
 {
     ITypeInfo *pTypeInfo;
@@ -1668,7 +1624,7 @@
 		}
 
 		char szStr[OLE_BUF_SIZ];
-		char *pszStr = GetMultiByte(THIS_ bstr, szStr,
+		char *pszStr = GetMultiByte(aTHX_ bstr, szStr,
 					    sizeof(szStr), cp);
 		if (strEQ(pszItf, pszStr)) {
 		    TYPEATTR *pImplTypeAttr;
@@ -1685,7 +1641,7 @@
 		    }
 		}
 
-		ReleaseBuffer(THIS_ pszStr, szStr);
+		ReleaseBuffer(aTHX_ pszStr, szStr);
 		pImplTypeInfo->Release();
 		if (bFound || FAILED(hr))
 		    break;
@@ -1712,9 +1668,9 @@
     OLECHAR wszGUID[80];
     int len = StringFromGUID2(*piid, wszGUID, sizeof(wszGUID)/sizeof(OLECHAR));
     char szStr[OLE_BUF_SIZ];
-    char *pszStr = GetMultiByte(THIS_ wszGUID, szStr, sizeof(szStr), cp);
+    char *pszStr = GetMultiByte(aTHX_ wszGUID, szStr, sizeof(szStr), cp);
     DBG(("FindIID: %s is %s", pszItf, pszStr));
-    ReleaseBuffer(THIS_ pszStr, szStr);
+    ReleaseBuffer(aTHX_ pszStr, szStr);
 #endif
 
     return S_OK;
@@ -1722,7 +1678,7 @@
 }   /* FindIID */
 
 HRESULT
-FindDefaultSource(CPERLarg_ WINOLEOBJECT *pObj, IID *piid,
+FindDefaultSource(pTHX_ WINOLEOBJECT *pObj, IID *piid,
 		  ITypeInfo **ppTypeInfo, UINT cp, LCID lcid)
 {
     HRESULT hr;
@@ -1738,7 +1694,7 @@
 					 piid);
 	pProvideClassInfo2->Release();
 	DBG(("GetGUID: hr=0x%08x\n", hr));
-	return FindIID(THIS_ pObj, NULL, piid, ppTypeInfo, cp, lcid);
+	return FindIID(aTHX_ pObj, NULL, piid, ppTypeInfo, cp, lcid);
     }
 
     IProvideClassInfo *pProvideClassInfo;
@@ -1817,7 +1773,7 @@
 }   /* FindDefaultSource */
 
 IEnumVARIANT *
-CreateEnumVARIANT(CPERLarg_ WINOLEOBJECT *pObj)
+CreateEnumVARIANT(pTHX_ WINOLEOBJECT *pObj)
 {
     unsigned int argErr;
     EXCEPINFO excepinfo;
@@ -1833,7 +1789,7 @@
     dispParams.cArgs = 0;
 
     HV *stash = SvSTASH(pObj->self);
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
 
     Zero(&excepinfo, 1, EXCEPINFO);
     hr = pObj->pDispatch->Invoke(DISPID_NEWENUM, IID_NULL,
@@ -1848,13 +1804,13 @@
 						     (void**)&pEnum);
     }
     VariantClear(&result);
-    CheckOleError(THIS_ stash, hr, &excepinfo);
+    CheckOleError(aTHX_ stash, hr, &excepinfo);
     return pEnum;
 
 }   /* CreateEnumVARIANT */
 
 SV *
-NextEnumElement(CPERLarg_ IEnumVARIANT *pEnum, HV *stash)
+NextEnumElement(pTHX_ IEnumVARIANT *pEnum, HV *stash)
 {
     HRESULT hr = S_OK;
     SV *sv = &PL_sv_undef;
@@ -1863,13 +1819,13 @@
     VariantInit(&variant);
     if (SUCCEEDED(pEnum->Next(1, &variant, NULL))) {
 	sv = newSV(0);
-	hr = SetSVFromVariantEx(THIS_ &variant, sv, stash);
+	hr = SetSVFromVariantEx(aTHX_ &variant, sv, stash);
     }
     VariantClear(&variant);
     if (FAILED(hr)) {
         SvREFCNT_dec(sv);
 	sv = &PL_sv_undef;
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
     }
     return sv;
 
@@ -1877,7 +1833,7 @@
 
 //------------------------------------------------------------------------
 
-EventSink::EventSink(CPERLarg_ WINOLEOBJECT *pObj, SV *events,
+EventSink::EventSink(pTHX_ WINOLEOBJECT *pObj, SV *events,
 		     REFIID riid, ITypeInfo *pTypeInfo)
 {
     DBG(("EventSink::EventSink\n"));
@@ -1886,20 +1842,26 @@
     m_iid = riid;
     m_pTypeInfo = pTypeInfo;
     m_refcount = 1;
-#ifdef PERL_OBJECT
-    m_PERL_OBJECT_THIS = PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    this->aTHX = aTHX;
 #endif
 }
 
 EventSink::~EventSink(void)
 {
-#ifdef PERL_OBJECT
-    CPERLarg = m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX = PERL_GET_THX;
+    PERL_SET_THX(this->aTHX);
 #endif
+
     DBG(("EventSink::~EventSink\n"));
     if (m_pTypeInfo)
 	m_pTypeInfo->Release();
     SvREFCNT_dec(m_events);
+
+#ifdef PERL_IMPLICIT_CONTEXT
+    PERL_SET_THX(aTHX);
+#endif
 }
 
 HRESULT
@@ -1928,15 +1890,21 @@
 EventSink::QueryInterface(REFIID iid, void **ppv)
 {
 #ifdef _DEBUG
-#   ifdef PERL_OBJECT
-    CPERLarg = m_PERL_OBJECT_THIS;
+#   ifdef PERL_IMPLICIT_CONTEXT
+    pTHX = PERL_GET_THX;
+    PERL_SET_THX(this->aTHX);
 #   endif
+
     OLECHAR wszGUID[80];
     int len = StringFromGUID2(iid, wszGUID, sizeof(wszGUID)/sizeof(OLECHAR));
     char szStr[OLE_BUF_SIZ];
-    char *pszStr = GetMultiByte(THIS_ wszGUID, szStr, sizeof(szStr), CP_ACP);
+    char *pszStr = GetMultiByte(aTHX_ wszGUID, szStr, sizeof(szStr), CP_ACP);
     DBG(("***QueryInterface %s\n", pszStr));
-    ReleaseBuffer(THIS_ pszStr, szStr);
+    ReleaseBuffer(aTHX_ pszStr, szStr);
+
+#   ifdef PERL_IMPLICIT_CONTEXT
+    PERL_SET_THX(aTHX);
+#   endif
 #endif
 
     if (iid == IID_IUnknown || iid == IID_IDispatch || iid == m_iid)
@@ -2010,8 +1978,9 @@
     EXCEPINFO *pexcepinfo,
     UINT *puArgErr)
 {
-#ifdef PERL_OBJECT
-    CPERLarg = m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX = PERL_GET_THX;
+    PERL_SET_THX(this->aTHX);
 #endif
 
     DBG(("***Invoke dispid=%d args=%d\n", dispidMember, pdispparams->cArgs));
@@ -2024,10 +1993,13 @@
 	hr = m_pTypeInfo->GetNames(dispidMember, &bstr, 1, &count);
 	if (FAILED(hr)) {
 	    DBG(("  GetNames failed: 0x%08x\n", hr));
+#ifdef PERL_IMPLICIT_CONTEXT
+            PERL_SET_THX(aTHX);
+#endif
 	    return S_OK;
 	}
 
-	event = sv_2mortal(sv_setwide(THIS_ NULL, bstr, CP_ACP));
+	event = sv_2mortal(sv_setbstr(aTHX_ NULL, bstr, CP_ACP));
 	SysFreeString(bstr);
     }
     else {
@@ -2072,7 +2044,7 @@
 	    DBG(("   Arg %d vt=0x%04x\n", i, V_VT(pVariant)));
 	    SV *sv = sv_newmortal();
 	    // XXX Check return code
-	    SetSVFromVariantEx(THIS_ pVariant, sv, SvSTASH(m_pObj->self), TRUE);
+	    SetSVFromVariantEx(aTHX_ pVariant, sv, SvSTASH(m_pObj->self), TRUE);
 	    XPUSHs(sv);
 	}
 	PUTBACK;
@@ -2082,38 +2054,36 @@
 	LEAVE;
     }
 
+#ifdef PERL_IMPLICIT_CONTEXT
+    PERL_SET_THX(aTHX);
+#endif
     return S_OK;
 }
 
-#ifdef _DEBUG
-#define Dummy(i) STDMETHODIMP EventSink::Dummy##i(void) \
-   {  DBG(("***Dummy%d\n", i)); return S_OK; }
-
-Dummy(1)  Dummy(2)  Dummy(3)  Dummy(4)  Dummy(5)
-Dummy(6)  Dummy(7)  Dummy(8)  Dummy(9)  Dummy(10)
-Dummy(11) Dummy(12) Dummy(13) Dummy(14) Dummy(15)
-Dummy(16) Dummy(17) Dummy(18) Dummy(19) Dummy(20)
-Dummy(21) Dummy(22) Dummy(23) Dummy(24) Dummy(25)
-#endif
-
 //------------------------------------------------------------------------
 
-Forwarder::Forwarder(CPERLarg_ HV *stash, SV *method)
+Forwarder::Forwarder(pTHX_ HV *stash, SV *method)
 {
     m_stash = stash; // XXX refcount?
     m_method = newSVsv(method);
     m_refcount = 1;
-#ifdef PERL_OBJECT
-    m_PERL_OBJECT_THIS = PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    this->aTHX = aTHX;
 #endif
 }
 
 Forwarder::~Forwarder(void)
 {
-#ifdef PERL_OBJECT
-    CPERLarg = m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX = PERL_GET_THX;
+    PERL_SET_THX(this->aTHX);
 #endif
+
     SvREFCNT_dec(m_method);
+
+#ifdef PERL_IMPLICIT_CONTEXT
+    PERL_SET_THX(aTHX);
+#endif
 }
 
 STDMETHODIMP
@@ -2181,8 +2151,9 @@
     EXCEPINFO *pexcepinfo,
     UINT *puArgErr)
 {
-#ifdef PERL_OBJECT
-    CPERLarg = m_PERL_OBJECT_THIS;
+#ifdef PERL_IMPLICIT_CONTEXT
+    pTHX = PERL_GET_THX;
+    PERL_SET_THX(this->aTHX);
 #endif
 
     DBG(("Forwarder::Invoke dispid=%d args=%d\n",
@@ -2196,7 +2167,7 @@
 	DBG(("   Arg %d vt=0x%04x\n", i, V_VT(pVariant)));
 	SV *sv = sv_newmortal();
 	// XXX Check return code
-	SetSVFromVariantEx(THIS_ pVariant, sv, m_stash, TRUE);
+	SetSVFromVariantEx(aTHX_ pVariant, sv, m_stash, TRUE);
 	XPUSHs(sv);
     }
     PUTBACK;
@@ -2204,13 +2175,18 @@
     SPAGAIN;
     FREETMPS;
     LEAVE;
+
+#ifdef PERL_IMPLICIT_CONTEXT
+    PERL_SET_THX(aTHX);
+#endif
+
     return S_OK;
 }
 
 //------------------------------------------------------------------------
 
 SV *
-SetSVFromGUID(CPERLarg_ REFGUID rguid)
+SetSVFromGUID(pTHX_ REFGUID rguid)
 {
     dSP;
     SV *sv = newSVsv(&PL_sv_undef);
@@ -2232,16 +2208,17 @@
 	OLECHAR wszGUID[80];
 	int len = StringFromGUID2(rguid, wszGUID,
 				  sizeof(wszGUID)/sizeof(OLECHAR));
-	if (len > 0) {
-	    wszGUID[len-2] = (OLECHAR) 0;
-	    sv_setwide(THIS_ sv, wszGUID+1, CP_ACP);
+	if (len > 3) {
+            BSTR bstr = SysAllocStringLen(wszGUID+1, len-3);
+	    sv_setbstr(aTHX_ sv, bstr, CP_ACP);
+            SysFreeString(bstr);
 	}
     }
     return sv;
 }
 
 HRESULT
-SetSafeArrayFromAV(CPERLarg_ AV* av, VARTYPE vt, SAFEARRAY *psa,
+SetSafeArrayFromAV(pTHX_ AV* av, VARTYPE vt, SAFEARRAY *psa,
 		   UINT cDims, UINT cp, LCID lcid)
 {
     HRESULT hr = SafeArrayLock(psa);
@@ -2293,12 +2270,12 @@
 		if (vt == VT_VARIANT) {
 		    hr = SafeArrayPtrOfIndex(psa, pix, (void**)&pElement);
 		    if (SUCCEEDED(hr))
-			hr = SetVariantFromSVEx(THIS_ *psv, pElement, cp, lcid);
+			hr = SetVariantFromSVEx(aTHX_ *psv, pElement, cp, lcid);
 		}
 		else {
 		    hr = SafeArrayPtrOfIndex(psa, pix, &V_BYREF(pElement));
 		    if (SUCCEEDED(hr))
-			hr = AssignVariantFromSV(THIS_ *psv, pElement,
+			hr = AssignVariantFromSV(aTHX_ *psv, pElement,
 						 cp, lcid);
 		}
 		if (hr == DISP_E_BADINDEX)
@@ -2325,7 +2302,7 @@
 }
 
 HRESULT
-SetVariantFromSVEx(CPERLarg_ SV* sv, VARIANT *pVariant, UINT cp, LCID lcid)
+SetVariantFromSVEx(pTHX_ SV* sv, VARIANT *pVariant, UINT cp, LCID lcid)
 {
     HRESULT hr = S_OK;
     VariantClear(pVariant);
@@ -2337,7 +2314,7 @@
     /* Objects */
     if (SvROK(sv)) {
 	if (sv_derived_from(sv, szWINOLE)) {
-	    WINOLEOBJECT *pObj = GetOleObject(THIS_ sv);
+	    WINOLEOBJECT *pObj = GetOleObject(aTHX_ sv);
 	    if (pObj) {
 		pObj->pDispatch->AddRef();
 		V_VT(pVariant) = VT_DISPATCH;
@@ -2349,7 +2326,7 @@
 
 	if (sv_derived_from(sv, szWINOLEVARIANT)) {
 	    WINOLEVARIANTOBJECT *pVarObj =
-		GetOleVariantObject(THIS_ sv);
+		GetOleVariantObject(aTHX_ sv);
 
 	    if (pVarObj) {
 		/* XXX Should we use VariantCopyInd? */
@@ -2423,7 +2400,7 @@
 	/* Create and fill VARIANT array */
 	SAFEARRAY *psa = SafeArrayCreate(VT_VARIANT, dim, psab);
 	if (psa)
-	    hr = SetSafeArrayFromAV(THIS_ (AV*)sv, VT_VARIANT, psa, dim,
+	    hr = SetSafeArrayFromAV(aTHX_ (AV*)sv, VT_VARIANT, psa, dim,
 				    cp, lcid);
 	else
 	    hr = E_OUTOFMEMORY;
@@ -2454,7 +2431,7 @@
     }
     else if (SvPOK(sv)) {
 	V_VT(pVariant) = VT_BSTR;
-	V_BSTR(pVariant) = AllocOleString(THIS_ SvPVX(sv), SvCUR(sv), cp);
+	V_BSTR(pVariant) = AllocOleString(aTHX_ SvPVX(sv), SvCUR(sv), cp);
     }
     else {
 	V_VT(pVariant) = VT_ERROR;
@@ -2466,14 +2443,14 @@
 }   /* SetVariantFromSVEx */
 
 HRESULT
-SetVariantFromSV(CPERLarg_ SV* sv, VARIANT *pVariant, UINT cp)
+SetVariantFromSV(pTHX_ SV* sv, VARIANT *pVariant, UINT cp)
 {
     /* old API for PerlScript compatibility */
-    return SetVariantFromSVEx(THIS_ sv, pVariant, cp, lcidDefault);
+    return SetVariantFromSVEx(aTHX_ sv, pVariant, cp, lcidDefault);
 }   /* SetVariantFromSV */
 
 HRESULT
-AssignVariantFromSV(CPERLarg_ SV* sv, VARIANT *pVariant, UINT cp, LCID lcid)
+AssignVariantFromSV(pTHX_ SV* sv, VARIANT *pVariant, UINT cp, LCID lcid)
 {
     /* This function is similar to SetVariantFromSVEx except that
      * it does NOT choose the variant type itself.
@@ -2564,7 +2541,7 @@
 	    STRLEN len;
 	    char *ptr = SvPV(sv, len);
 	    V_VT(&variant) = VT_BSTR;
-	    V_BSTR(&variant) = AllocOleString(THIS_ ptr, len, cp);
+	    V_BSTR(&variant) = AllocOleString(aTHX_ ptr, len, cp);
 	}
 
 	VARTYPE vt_base = vt & ~VT_BYREF;
@@ -2591,7 +2568,7 @@
     {
 	STRLEN len;
 	char *ptr = SvPV(sv, len);
-	BSTR bstr = AllocOleString(THIS_ ptr, len, cp);
+	BSTR bstr = AllocOleString(aTHX_ ptr, len, cp);
 
 	if (vt & VT_BYREF) {
 	    SysFreeString(*V_BSTRREF(pVariant));
@@ -2617,7 +2594,7 @@
 	}
 	if (sv_isobject(sv)) {
 	    /* Argument MUST be a valid Perl OLE object! */
-	    WINOLEOBJECT *pObj = GetOleObject(THIS_ sv);
+	    WINOLEOBJECT *pObj = GetOleObject(aTHX_ sv);
 	    if (pObj) {
 		pObj->pDispatch->AddRef();
 		if (vt & VT_BYREF)
@@ -2641,7 +2618,7 @@
 
     case VT_VARIANT:
 	if (vt & VT_BYREF)
-	    hr = SetVariantFromSVEx(THIS_ sv, V_VARIANTREF(pVariant), cp, lcid);
+	    hr = SetVariantFromSVEx(aTHX_ sv, V_VARIANTREF(pVariant), cp, lcid);
 	else {
 	    warn(MY_VERSION ": AssignVariantFromSV() with invalid type: "
 		 "VT_VARIANT without VT_BYREF");
@@ -2653,7 +2630,7 @@
     {
 	/* Argument MUST be a valid Perl OLE object! */
 	/* Query IUnknown interface to allow identity tests */
-	WINOLEOBJECT *pObj = GetOleObject(THIS_ sv);
+	WINOLEOBJECT *pObj = GetOleObject(aTHX_ sv);
 	if (pObj) {
 	    IUnknown *punk;
 	    hr = pObj->pDispatch->QueryInterface(IID_IUnknown, (void**)&punk);
@@ -2681,7 +2658,7 @@
 	VARIANT variant;
 	VariantInit(&variant);
 	V_VT(&variant) = VT_BSTR;
-	V_BSTR(&variant) = AllocOleString(THIS_ ptr, len, cp);
+	V_BSTR(&variant) = AllocOleString(aTHX_ ptr, len, cp);
 
 	hr = VariantChangeTypeEx(&variant, &variant, lcid, 0, VT_DECIMAL);
 	if (SUCCEEDED(hr)) {
@@ -2718,7 +2695,7 @@
 }   /* AssignVariantFromSV */
 
 HRESULT
-SetSVFromVariantEx(CPERLarg_ VARIANTARG *pVariant, SV* sv, HV *stash,
+SetSVFromVariantEx(pTHX_ VARIANTARG *pVariant, SV* sv, HV *stash,
 		   BOOL bByRefObj)
 {
     HRESULT hr = S_OK;
@@ -2741,10 +2718,10 @@
 	hr = VariantCopy(&pVarObj->variant, pVariant);
 	if (FAILED(hr)) {
 	    Safefree(pVarObj);
-	    ReportOleError(THIS_ stash, hr);
+	    ReportOleError(aTHX_ stash, hr);
 	}
 
-	AddToObjectChain(THIS_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
+	AddToObjectChain(aTHX_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
 	SV *classname = newSVpv(HvNAME(stash), 0);
 	sv_catpvn(classname, "::Variant", 9);
 	sv_setref_pv(sv, SvPVX(classname), pVarObj);
@@ -2807,7 +2784,7 @@
 		    break;
 
 		SV *val = newSV(0);
-		hr = SetSVFromVariantEx(THIS_ &variant, val, stash);
+		hr = SetSVFromVariantEx(aTHX_ &variant, val, stash);
 		if (FAILED(hr)) {
 		    SvREFCNT_dec(val);
 		    break;
@@ -2877,12 +2854,12 @@
 
     case VT_BSTR:
     {
-	UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+	UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
 	if (V_ISBYREF(pVariant))
-	    sv_setwide(THIS_ sv, *V_BSTRREF(pVariant), cp);
+	    sv_setbstr(aTHX_ sv, *V_BSTRREF(pVariant), cp);
 	else
-	    sv_setwide(THIS_ sv, V_BSTR(pVariant), cp);
+	    sv_setbstr(aTHX_ sv, V_BSTR(pVariant), cp);
 	break;
     }
 
@@ -2897,11 +2874,11 @@
 	hr = VariantCopy(&pVarObj->variant, pVariant);
 	if (FAILED(hr)) {
 	    Safefree(pVarObj);
-	    ReportOleError(THIS_ stash, hr, NULL, NULL);
+	    ReportOleError(aTHX_ stash, hr, NULL, NULL);
             break;
 	}
 
-	AddToObjectChain(THIS_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
+	AddToObjectChain(aTHX_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
 	classname = newSVpv(HvNAME(stash), 0);
 	sv_catpvn(classname, "::Variant", 9);
 	sv_setref_pv(sv, SvPVX(classname), pVarObj);
@@ -2927,7 +2904,7 @@
 
 	if (pDispatch) {
 	    pDispatch->AddRef();
-	    sv_setsv(sv, CreatePerlObject(THIS_ stash, pDispatch, NULL));
+	    sv_setsv(sv, CreatePerlObject(aTHX_ stash, pDispatch, NULL));
 	}
 	break;
     }
@@ -2945,7 +2922,7 @@
 	if (punk &&
 	    SUCCEEDED(punk->QueryInterface(IID_IDispatch, (void**)&pDispatch)))
 	{
-	    sv_setsv(sv, CreatePerlObject(THIS_ stash, pDispatch, NULL));
+	    sv_setsv(sv, CreatePerlObject(aTHX_ stash, pDispatch, NULL));
 	}
 	break;
     }
@@ -2964,14 +2941,14 @@
     case VT_CY:
     default:
     {
-	LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-	UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+	LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+	UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 	VARIANT variant;
 
 	VariantInit(&variant);
 	hr = VariantChangeTypeEx(&variant, pVariant, lcid, 0, VT_BSTR);
 	if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR)
-	    sv_setwide(THIS_ sv, V_BSTR(&variant), cp);
+	    sv_setbstr(aTHX_ sv, V_BSTR(&variant), cp);
 	VariantClear(&variant);
 	break;
     }
@@ -2982,13 +2959,13 @@
 }   /* SetSVFromVariantEx */
 
 HRESULT
-SetSVFromVariant(CPERLarg_ VARIANTARG *pVariant, SV* sv, HV *stash)
+SetSVFromVariant(pTHX_ VARIANTARG *pVariant, SV* sv, HV *stash)
 {
-    return SetSVFromVariantEx(THIS_ pVariant, sv, stash);
+    return SetSVFromVariantEx(aTHX_ pVariant, sv, stash);
 }
 
 IV
-GetLocaleNumber(CPERLarg_ HV *hv, char *key, LCID lcid, LCTYPE lctype)
+GetLocaleNumber(pTHX_ HV *hv, char *key, LCID lcid, LCTYPE lctype)
 {
     if (hv) {
 	SV **psv = hv_fetch(hv, key, strlen(key), FALSE);
@@ -2996,17 +2973,51 @@
 	    return SvIV(*psv);
     }
 
-    char *info;
-    int len = GetLocaleInfo(lcid, lctype, NULL, 0);
-    New(0, info, len, char);
-    GetLocaleInfo(lcid, lctype, info, len);
-    IV number = atol(info);
-    Safefree(info);
+    IV number;
+    if (USING_WIDE()) {
+	WCHAR *info;
+	int len = GetLocaleInfoW(lcid, lctype, NULL, 0);
+	New(0, info, len, WCHAR);
+	GetLocaleInfoW(lcid, lctype, info, len);
+	number = _wtol(info);
+	Safefree(info);
+    }
+    else {
+	char *info;
+	int len = GetLocaleInfoA(lcid, lctype, NULL, 0);
+	New(0, info, len, char);
+	GetLocaleInfoA(lcid, lctype, info, len);
+	number = atol(info);
+	Safefree(info);
+    }
     return number;
 }
 
+WCHAR *
+GetLocaleStringW(pTHX_ HV *hv, char *key, LCID lcid, LCTYPE lctype)
+{
+    STRLEN len;
+    SV *sv;
+    if (hv) {
+	SV **psv = hv_fetch(hv, key, strlen(key), FALSE);
+	if (psv) {
+	    char* ptr = SvPV(*psv, len);
+	    ++len;
+	    sv = sv_2mortal(newSV(len*sizeof(WCHAR)));
+	    WCHAR* wptr = (WCHAR*)SvPVX(sv);
+	    A2WHELPER(ptr, wptr, len*sizeof(WCHAR));
+	    return wptr;
+	}
+    }
+
+    len = GetLocaleInfoW(lcid, lctype, NULL, 0);
+    sv = sv_2mortal(newSV(len*2));
+    GetLocaleInfoW(lcid, lctype, (WCHAR*)SvPVX(sv), len);
+    return (WCHAR*)SvPVX(sv);
+}
+
 char *
-GetLocaleString(CPERLarg_ HV *hv, char *key, LCID lcid, LCTYPE lctype)
+GetLocaleString(pTHX_ HV *hv, char *key, LCID lcid, LCTYPE lctype)
 {
     if (hv) {
 	SV **psv = hv_fetch(hv, key, strlen(key), FALSE);
@@ -3014,14 +3025,14 @@
 	    return SvPV_nolen(*psv);
     }
 
-    int len = GetLocaleInfo(lcid, lctype, NULL, 0);
+    int len = GetLocaleInfoA(lcid, lctype, NULL, 0);
     SV *sv = sv_2mortal(newSV(len));
-    GetLocaleInfo(lcid, lctype, SvPVX(sv), len);
+    GetLocaleInfoA(lcid, lctype, SvPVX(sv), len);
     return SvPVX(sv);
 }
 
 void
-Initialize(CPERLarg_ HV *stash, DWORD dwCoInit=COINIT_MULTITHREADED)
+Initialize(pTHX_ HV *stash, DWORD dwCoInit=COINIT_MULTITHREADED)
 {
     dPERINTERP;
 
@@ -3053,7 +3064,7 @@
 	}
 
 	if (FAILED(hr) && hr != RPC_E_CHANGED_MODE)
-	    ReportOleError(THIS_ stash, hr);
+	    ReportOleError(aTHX_ stash, hr);
     }
 
     LeaveCriticalSection(&g_CriticalSection);
@@ -3061,7 +3072,7 @@
 }   /* Initialize */
 
 void
-Uninitialize(CPERLarg_ PERINTERP *pInterp)
+Uninitialize(pTHX_ PERINTERP *pInterp)
 {
     DBG(("Uninitialize\n"));
     EnterCriticalSection(&g_CriticalSection);
@@ -3073,7 +3084,7 @@
 
 	    switch (pHeader->lMagic) {
 	    case WINOLE_MAGIC:
-		ReleasePerlObject(THIS_ (WINOLEOBJECT*)pHeader);
+		ReleasePerlObject(aTHX_ (WINOLEOBJECT*)pHeader);
 		break;
 
 	    case WINOLEENUM_MAGIC: {
@@ -3127,7 +3138,7 @@
 }   /* Uninitialize */
 
 static void
-AtExit(pTHX_ CPERLarg_ void *pVoid)
+AtExit(pTHX_ void *pVoid)
 {
     PERINTERP *pInterp = (PERINTERP*)pVoid;
 
@@ -3136,7 +3147,7 @@
 	FreeLibrary(g_hOLE32);
     if (g_hHHCTRL)
 	FreeLibrary(g_hHHCTRL);
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
+#ifdef PERL_IMPLICIT_CONTEXT
     Safefree(pInterp);
 #endif
     DBG(("AtExit done\n"));
@@ -3144,18 +3155,13 @@
 }   /* AtExit */
 
 void
-Bootstrap(CPERLarg)
+Bootstrap(pTHX)
 {
     dSP;
-#if defined(MULTIPLICITY) || defined(PERL_OBJECT)
+#ifdef PERL_IMPLICIT_CONTEXT
     PERINTERP *pInterp;
     New(0, pInterp, 1, PERINTERP);
-
-#   if (PATCHLEVEL == 4) && (SUBVERSION < 68)
-    SV *sv = perl_get_sv(MY_VERSION, TRUE);
-#   else
     SV *sv = *hv_fetch(PL_modglobal, MY_VERSION, sizeof(MY_VERSION)-1, TRUE);
-#   endif
 
     if (SvOK(sv))
 	warn(MY_VERSION ": Per-interpreter data already set");
@@ -3189,15 +3195,12 @@
     SPAGAIN;
 
     SvREFCNT_dec(cmd);
-
-#if (PATCHLEVEL > 4) || (SUBVERSION >= 68)
     perl_atexit(AtExit, INTERP);
-#endif
 
 }   /* Bootstrap */
 
 BOOL
-CallObjectMethod(CPERLarg_ SV **mark, I32 ax, I32 items, char *pszMethod)
+CallObjectMethod(pTHX_ SV **mark, I32 ax, I32 items, char *pszMethod)
 {
     /* If the 1st arg on the stack is a Win32::OLE object then the method
      * is called as an object method through Win32::OLE::Dispatch (like
@@ -3239,9 +3242,7 @@
 
 }   /* CallObjectMethod */
 
-#if defined (__cplusplus)
-}
-#endif
+}   /* extern "C" */
 
 /*##########################################################################*/
 
@@ -3250,7 +3251,7 @@
 PROTOTYPES: DISABLE
 
 BOOT:
-    Bootstrap(PERL_OBJECT_THIS);
+    Bootstrap(aTHX);
 
 void
 Initialize(...)
@@ -3267,7 +3268,7 @@
                           "MessageLoop", "QuitMessageLoop",
 			  "FreeUnusedLibraries", "_Unique"};
 
-    if (CallObjectMethod(THIS_ mark, ax, items, paszMethod[ix]))
+    if (CallObjectMethod(aTHX_ mark, ax, items, paszMethod[ix]))
 	return;
 
     DBG(("Win32::OLE->%s()\n", paszMethod[ix]));
@@ -3278,7 +3279,7 @@
     }
 
     HV *stash = gv_stashsv(ST(0), TRUE);
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
     switch (ix) {
     case 0: {		// Initialize
@@ -3286,12 +3287,12 @@
 	if (items > 1 && SvOK(ST(1)))
 	    dwCoInit = SvIV(ST(1));
 
-	Initialize(THIS_ gv_stashsv(ST(0), TRUE), dwCoInit);
+	Initialize(aTHX_ gv_stashsv(ST(0), TRUE), dwCoInit);
 	break;
     }
     case 1: {		// Uninitialize
 	dPERINTERP;
-	Uninitialize(THIS_ INTERP);
+	Uninitialize(aTHX_ INTERP);
 	break;
     }
     case 2:		// SpinMessageLoop
@@ -3337,7 +3338,7 @@
     OLECHAR *pBuffer;
     HRESULT hr;
 
-    if (CallObjectMethod(THIS_ mark, ax, items, "new"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "new"))
 	return;
 
     if (items < 2 || items > 3) {
@@ -3349,13 +3350,13 @@
     HV *stash = gv_stashsv(self, TRUE);
     SV *progid = ST(1);
     SV *destroy = NULL;
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
-    Initialize(THIS_ stash);
-    SetLastOleError(THIS_ stash);
+    Initialize(aTHX_ stash);
+    SetLastOleError(aTHX_ stash);
 
     if (items == 3)
-	destroy = CheckDestroyFunction(THIS_ ST(2), "Win32::OLE->new");
+	destroy = CheckDestroyFunction(aTHX_ ST(2), "Win32::OLE->new");
 
     ST(0) = &PL_sv_undef;
 
@@ -3363,18 +3364,18 @@
     char *pszProgID;
     if (!SvROK(progid) || SvTYPE(SvRV(progid)) != SVt_PVAV) {
 	pszProgID = SvPV_nolen(progid);
-	pBuffer = GetWideChar(THIS_ pszProgID, Buffer, OLE_BUF_SIZ, cp);
+	pBuffer = GetWideChar(aTHX_ pszProgID, Buffer, OLE_BUF_SIZ, cp);
 	if (isalpha(pszProgID[0]))
 	    hr = CLSIDFromProgID(pBuffer, &clsid);
 	else
 	    hr = CLSIDFromString(pBuffer, &clsid);
-	ReleaseBuffer(THIS_ pBuffer, Buffer);
+	ReleaseBuffer(aTHX_ pBuffer, Buffer);
 	if (SUCCEEDED(hr)) {
 	    hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER,
 				  IID_IDispatch, (void**)&pDispatch);
 	}
-	if (!CheckOleError(THIS_ stash, hr)) {
-	    ST(0) = CreatePerlObject(THIS_ stash, pDispatch, destroy);
+	if (!CheckOleError(aTHX_ stash, hr)) {
+	    ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, destroy);
 	    DBG(("Win32::OLE::new |%lx| |%lx|\n", ST(0), pDispatch));
 	}
 	XSRETURN(1);
@@ -3384,7 +3385,7 @@
     dPERINTERP;
     if (!g_pfnCoCreateInstanceEx) {
 	hr = HRESULT_FROM_WIN32(ERROR_SERVICE_DOES_NOT_EXIST);
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	XSRETURN(1);
     }
 
@@ -3401,23 +3402,23 @@
     char *pszHost = NULL;
     if (SvPOK(host)) {
 	pszHost = SvPVX(host);
-	if (IsLocalMachine(THIS_ pszHost))
+	if (IsLocalMachine(aTHX_ pszHost))
 	    pszHost = NULL;
     }
 
     /* determine CLSID */
     pszProgID = SvPV_nolen(progid);
-    pBuffer = GetWideChar(THIS_ pszProgID, Buffer, OLE_BUF_SIZ, cp);
+    pBuffer = GetWideChar(aTHX_ pszProgID, Buffer, OLE_BUF_SIZ, cp);
     if (isalpha(pszProgID[0])) {
 	hr = CLSIDFromProgID(pBuffer, &clsid);
 	if (FAILED(hr) && pszHost)
-	    hr = CLSIDFromRemoteRegistry(THIS_ pszHost, pszProgID, &clsid);
+	    hr = CLSIDFromRemoteRegistry(aTHX_ pszHost, pszProgID, &clsid);
     }
     else
         hr = CLSIDFromString(pBuffer, &clsid);
-    ReleaseBuffer(THIS_ pBuffer, Buffer);
+    ReleaseBuffer(aTHX_ pBuffer, Buffer);
     if (FAILED(hr)) {
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	XSRETURN(1);
     }
 
@@ -3429,7 +3430,7 @@
 
     Zero(&ServerInfo, 1, COSERVERINFO);
     if (pszHost)
-	ServerInfo.pwszName = GetWideChar(THIS_ pszHost, ServerName,
+	ServerInfo.pwszName = GetWideChar(aTHX_ pszHost, ServerName,
 					  OLE_BUF_SIZ, cp);
     else
 	clsctx = CLSCTX_SERVER;
@@ -3440,10 +3441,10 @@
     /* create instance on remote server */
     hr = g_pfnCoCreateInstanceEx(clsid, NULL, clsctx, &ServerInfo,
 				  1, &multi_qi);
-    ReleaseBuffer(THIS_ ServerInfo.pwszName, ServerName);
-    if (!CheckOleError(THIS_ stash, hr)) {
+    ReleaseBuffer(aTHX_ ServerInfo.pwszName, ServerName);
+    if (!CheckOleError(aTHX_ stash, hr)) {
 	pDispatch = (IDispatch*)multi_qi.pItf;
-	ST(0) = CreatePerlObject(THIS_ stash, pDispatch, destroy);
+	ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, destroy);
 	DBG(("Win32::OLE::new |%lx| |%lx|\n", ST(0), pDispatch));
     }
     XSRETURN(1);
@@ -3454,11 +3455,11 @@
     SV *self
 PPCODE:
 {
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self, TRUE);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self, TRUE);
     DBG(("Win32::OLE::DESTROY |%lx| |%lx|\n", pObj,
 	 pObj ? pObj->pDispatch : NULL));
     if (pObj) {
-	ReleasePerlObject(THIS_ pObj);
+	ReleasePerlObject(aTHX_ pObj);
 	pObj->flags |= OBJFLAG_DESTROYED;
     }
     XSRETURN_EMPTY;
@@ -3499,16 +3500,16 @@
 	XSRETURN(1);
     }
 
-    pObj = GetOleObject(THIS_ self);
+    pObj = GetOleObject(aTHX_ self);
     if (!pObj) {
 	XSRETURN(1);
     }
 
     HV *stash = SvSTASH(pObj->self);
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
     /* allow [wFlags, 'Method'] instead of 'Method' */
     if (SvROK(method) && (sv = SvRV(method)) &&	SvTYPE(sv) == SVt_PVAV &&
@@ -3521,7 +3522,7 @@
     if (SvPOK(method)) {
 	buffer = SvPV(method, length);
 	if (length > 0) {
-            int newenum = QueryPkgVar(THIS_ stash, _NEWENUM_NAME, _NEWENUM_LEN);
+            int newenum = QueryPkgVar(aTHX_ stash, _NEWENUM_NAME, _NEWENUM_LEN);
             if (newenum && strEQ(buffer, "_NewEnum")) {
                 AV *av = newAV();
                 PUSHMARK(sp);
@@ -3536,11 +3537,11 @@
 		XSRETURN_YES;
             }
 
-	    hr = GetHashedDispID(THIS_ pObj, buffer, length, dispID, lcid, cp);
+	    hr = GetHashedDispID(aTHX_ pObj, buffer, length, dispID, lcid, cp);
 	    if (FAILED(hr)) {
 		if (PL_hints & HINT_STRICT_SUBS) {
 		    err = newSVpvf(" in GetIDsOfNames of \"%s\"", buffer);
-		    ReportOleError(THIS_ stash, hr, NULL, sv_2mortal(err));
+		    ReportOleError(aTHX_ stash, hr, NULL, sv_2mortal(err));
 		}
 		XSRETURN_EMPTY;
 	    }
@@ -3582,12 +3583,12 @@
 	New(0, rgszNames, 1+dispParams.cNamedArgs, OLECHAR*);
 	New(0, rgdispids, 1+dispParams.cNamedArgs, DISPID);
 
-	rgszNames[0] = AllocOleString(THIS_ buffer, length, cp);
+	rgszNames[0] = AllocOleString(aTHX_ buffer, length, cp);
 	hv_iterinit(hv);
 	for (index = 0; index < dispParams.cNamedArgs; ++index) {
 	    rghe[index] = hv_iternext(hv);
 	    char *pszName = hv_iterkey(rghe[index], &len);
-	    rgszNames[1+index] = AllocOleString(THIS_ pszName, len, cp);
+	    rgszNames[1+index] = AllocOleString(aTHX_ pszName, len, cp);
 	}
 
 	hr = pObj->pDispatch->GetIDsOfNames(IID_NULL, rgszNames,
@@ -3596,7 +3597,7 @@
 	if (SUCCEEDED(hr)) {
 	    for (index = 0; index < dispParams.cNamedArgs; ++index) {
 		dispParams.rgdispidNamedArgs[index] = rgdispids[index+1];
-		hr = SetVariantFromSVEx(THIS_ hv_iterval(hv, rghe[index]),
+		hr = SetVariantFromSVEx(aTHX_ hv_iterval(hv, rghe[index]),
 					&dispParams.rgvarg[index], cp, lcid);
 		if (FAILED(hr))
 		    break;
@@ -3640,7 +3641,7 @@
 
 	for(index = dispParams.cNamedArgs; index < dispParams.cArgs; ++index) {
 	    SV *sv = ST(items-1-(index-dispParams.cNamedArgs));
-	    hr = SetVariantFromSVEx(THIS_ sv, &dispParams.rgvarg[index],
+	    hr = SetVariantFromSVEx(aTHX_ sv, &dispParams.rgvarg[index],
 				    cp, lcid);
 	    if (FAILED(hr))
 		goto Cleanup;
@@ -3671,7 +3672,7 @@
     if (SUCCEEDED(hr)) {
 	if (sv_isobject(retval) && sv_derived_from(retval, szWINOLEVARIANT)) {
 	    WINOLEVARIANTOBJECT *pVarObj =
-		GetOleVariantObject(THIS_ retval);
+		GetOleVariantObject(aTHX_ retval);
 
 	    if (pVarObj) {
 		VariantClear(&pVarObj->byref);
@@ -3681,7 +3682,7 @@
 	    }
 	}
 	else {
-	    hr = SetSVFromVariantEx(THIS_ &result, retval, stash);
+	    hr = SetSVFromVariantEx(aTHX_ &result, retval, stash);
 	    ST(0) = &PL_sv_yes;
 	}
     }
@@ -3731,7 +3732,7 @@
     if (dispParams.rgdispidNamedArgs != &dispIDParam)
 	Safefree(dispParams.rgdispidNamedArgs);
 
-    CheckOleError(THIS_ stash, hr, &excepinfo, err);
+    CheckOleError(aTHX_ stash, hr, &excepinfo, err);
 
     XSRETURN(1);
 }
@@ -3740,7 +3741,7 @@
 EnumAllObjects(...)
 PPCODE:
 {
-    if (CallObjectMethod(THIS_ mark, ax, items, "EnumAllObjects"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "EnumAllObjects"))
 	return;
 
     if (items > 2) {
@@ -3790,7 +3791,7 @@
     SV *method
 PPCODE:
 {
-    if (CallObjectMethod(THIS_ mark, ax, items, "Forward"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "Forward"))
 	return;
 
     if (!SvROK(method) || SvTYPE(SvRV(method)) != SVt_PVCV) {
@@ -3799,8 +3800,8 @@
     }
 
     HV *stash = gv_stashsv(self, TRUE);
-    IDispatch *pDispatch = new Forwarder(THIS_ stash, method);
-    ST(0) = CreatePerlObject(THIS_ stash, pDispatch, NULL);
+    IDispatch *pDispatch = new Forwarder(aTHX_ stash, method);
+    ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, NULL);
     XSRETURN(1);
 }
 
@@ -3816,7 +3817,7 @@
     IUnknown *pUnknown;
     IDispatch *pDispatch;
 
-    if (CallObjectMethod(THIS_ mark, ax, items, "GetActiveObject"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "GetActiveObject"))
 	return;
 
     if (items < 2 || items > 3) {
@@ -3828,23 +3829,23 @@
     HV *stash = gv_stashsv(self, TRUE);
     SV *progid = ST(1);
     SV *destroy = NULL;
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
-    Initialize(THIS_ stash);
-    SetLastOleError(THIS_ stash);
+    Initialize(aTHX_ stash);
+    SetLastOleError(aTHX_ stash);
 
     if (items == 3)
-	destroy = CheckDestroyFunction(THIS_ ST(2),
+	destroy = CheckDestroyFunction(aTHX_ ST(2),
 				       "Win32::OLE->GetActiveObject");
 
     buffer = SvPV_nolen(progid);
-    pBuffer = GetWideChar(THIS_ buffer, Buffer, OLE_BUF_SIZ, cp);
+    pBuffer = GetWideChar(aTHX_ buffer, Buffer, OLE_BUF_SIZ, cp);
     if (isalpha(buffer[0]))
         hr = CLSIDFromProgID(pBuffer, &clsid);
     else
         hr = CLSIDFromString(pBuffer, &clsid);
-    ReleaseBuffer(THIS_ pBuffer, Buffer);
-    if (CheckOleError(THIS_ stash, hr))
+    ReleaseBuffer(aTHX_ pBuffer, Buffer);
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     hr = GetActiveObject(clsid, 0, &pUnknown);
@@ -3854,10 +3855,10 @@
 
     hr = pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);
     pUnknown->Release();
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
-    ST(0) = CreatePerlObject(THIS_ stash, pDispatch, destroy);
+    ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, destroy);
     DBG(("Win32::OLE::GetActiveObject |%lx| |%lx|\n", ST(0), pDispatch));
     XSRETURN(1);
 }
@@ -3875,7 +3876,7 @@
     ULONG ulEaten;
     HRESULT hr;
 
-    if (CallObjectMethod(THIS_ mark, ax, items, "GetObject"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "GetObject"))
 	return;
 
     if (items < 2 || items > 3) {
@@ -3887,27 +3888,27 @@
     HV *stash = gv_stashsv(self, TRUE);
     SV *pathname = ST(1);
     SV *destroy = NULL;
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
-    Initialize(THIS_ stash);
-    SetLastOleError(THIS_ stash);
+    Initialize(aTHX_ stash);
+    SetLastOleError(aTHX_ stash);
 
     if (items == 3)
-	destroy = CheckDestroyFunction(THIS_ ST(2), "Win32::OLE->GetObject");
+	destroy = CheckDestroyFunction(aTHX_ ST(2), "Win32::OLE->GetObject");
 
     hr = CreateBindCtx(0, &pBindCtx);
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     buffer = SvPV_nolen(pathname);
-    pBuffer = GetWideChar(THIS_ buffer, Buffer, OLE_BUF_SIZ, cp);
+    pBuffer = GetWideChar(aTHX_ buffer, Buffer, OLE_BUF_SIZ, cp);
     hr = MkParseDisplayName(pBindCtx, pBuffer, &ulEaten, &pMoniker);
-    ReleaseBuffer(THIS_ pBuffer, Buffer);
+    ReleaseBuffer(aTHX_ pBuffer, Buffer);
     if (FAILED(hr)) {
 	pBindCtx->Release();
 	SV *sv = sv_newmortal();
 	sv_setpvf(sv, "after character %lu in \"%s\"", ulEaten, buffer);
-	ReportOleError(THIS_ stash, hr, NULL, sv);
+	ReportOleError(aTHX_ stash, hr, NULL, sv);
 	XSRETURN_EMPTY;
     }
 
@@ -3915,10 +3916,10 @@
 				 (void**)&pDispatch);
     pBindCtx->Release();
     pMoniker->Release();
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
-    ST(0) = CreatePerlObject(THIS_ stash, pDispatch, destroy);
+    ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, destroy);
     XSRETURN(1);
 }
 
@@ -3927,7 +3928,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -3935,21 +3936,21 @@
     TYPEATTR  *pTypeAttr;
 
     HV *stash = gv_stashsv(self, TRUE);
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
 
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
     HRESULT hr = pObj->pDispatch->GetTypeInfo(0, lcid, &pTypeInfo);
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr));
+    ST(0) = sv_2mortal(CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr));
     XSRETURN(1);
 }
 
@@ -3959,7 +3960,7 @@
     SV *itf
 PPCODE:
 {
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -3972,29 +3973,29 @@
 
     DBG(("QueryInterface(%s)\n", pszItf));
     HV *stash = SvSTASH(pObj->self);
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
-    HRESULT hr = FindIID(THIS_ pObj, pszItf, &iid, NULL, cp, lcid);
-    if (CheckOleError(THIS_ stash, hr))
+    HRESULT hr = FindIID(aTHX_ pObj, pszItf, &iid, NULL, cp, lcid);
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     IUnknown *pUnknown;
     hr = pObj->pDispatch->QueryInterface(iid, (void**)&pUnknown);
     DBG(("  QueryInterface(iid): 0x%08x\n", hr));
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
         XSRETURN_EMPTY;
 
     IDispatch *pDispatch;
     hr = pUnknown->QueryInterface(IID_IDispatch, (void**)&pDispatch);
     DBG(("  QueryInterface(IDispatch): 0x%08x\n", hr));
     pUnknown->Release();
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
         XSRETURN_EMPTY;
 
-    ST(0) = CreatePerlObject(THIS_ stash, pDispatch, NULL);
+    ST(0) = CreatePerlObject(aTHX_ stash, pDispatch, NULL);
     DBG(("Win32::OLE::QueryInterface |%lx| |%lx|\n", ST(0), pDispatch));
     XSRETURN(1);
 }
@@ -4003,7 +4004,7 @@
 QueryObjectType(...)
 PPCODE:
 {
-    if (CallObjectMethod(THIS_ mark, ax, items, "QueryObjectType"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "QueryObjectType"))
 	return;
 
     if (items != 2) {
@@ -4018,7 +4019,7 @@
 	XSRETURN_EMPTY;
     }
 
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ object);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ object);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -4032,12 +4033,12 @@
 	XSRETURN_EMPTY;
 
     HV *stash = gv_stashsv(ST(0), TRUE);
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
     hr = pObj->pDispatch->GetTypeInfo(0, lcid, &pTypeInfo);
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     /* Return ('TypeLib Name', 'Class Name') in array context */
@@ -4045,7 +4046,7 @@
 	hr = pTypeInfo->GetContainingTypeLib(&pTypeLib, &count);
 	if (FAILED(hr)) {
 	    pTypeInfo->Release();
-	    ReportOleError(THIS_ stash, hr);
+	    ReportOleError(aTHX_ stash, hr);
 	    XSRETURN_EMPTY;
 	}
 
@@ -4053,20 +4054,20 @@
 	pTypeLib->Release();
 	if (FAILED(hr)) {
 	    pTypeInfo->Release();
-	    ReportOleError(THIS_ stash, hr);
+	    ReportOleError(aTHX_ stash, hr);
 	    XSRETURN_EMPTY;
 	}
 
-	PUSHs(sv_2mortal(sv_setwide(THIS_ NULL, bstr, cp)));
+	PUSHs(sv_2mortal(sv_setbstr(aTHX_ NULL, bstr, cp)));
 	SysFreeString(bstr);
     }
 
     hr = pTypeInfo->GetDocumentation(MEMBERID_NIL, &bstr, NULL, NULL, NULL);
     pTypeInfo->Release();
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
-    PUSHs(sv_2mortal(sv_setwide(THIS_ NULL, bstr, cp)));
+    PUSHs(sv_2mortal(sv_setbstr(aTHX_ NULL, bstr, cp)));
     SysFreeString(bstr);
 }
 
@@ -4074,7 +4075,7 @@
 WithEvents(...)
 PPCODE:
 {
-    if (CallObjectMethod(THIS_ mark, ax, items, "WithEvents"))
+    if (CallObjectMethod(aTHX_ mark, ax, items, "WithEvents"))
 	return;
 
     if (items < 2) {
@@ -4082,7 +4083,7 @@
 	XSRETURN_EMPTY;
     }
 
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ ST(1));
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ ST(1));
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -4100,13 +4101,13 @@
 
     // make sure we are running in a single threaded apartment
     HRESULT hr = CoInitialize(NULL);
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
     CoUninitialize();
 
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
-    SetLastOleError(THIS_ stash);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
+    SetLastOleError(aTHX_ stash);
 
     IID iid;
     ITypeInfo *pTypeInfo = NULL;
@@ -4115,7 +4116,7 @@
     if (items > 3) {
 	SV *itf = ST(3);
 	if (sv_isobject(itf) && sv_derived_from(itf, szWINOLETYPEINFO)) {
-	    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ itf);
+	    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ itf);
 	    if (!pObj)
 		XSRETURN_EMPTY;
 
@@ -4174,19 +4175,19 @@
 	else { /* interface _not_ a Win32::OLE::TypeInfo object */
 	    char *pszItf = SvPV_nolen(itf);
 	    if (isalpha(pszItf[0]))
-		hr = FindIID(THIS_ pObj, pszItf, &iid, &pTypeInfo, cp, lcid);
+		hr = FindIID(aTHX_ pObj, pszItf, &iid, &pTypeInfo, cp, lcid);
 	    else {
 		OLECHAR Buffer[OLE_BUF_SIZ];
-		OLECHAR *pBuffer = GetWideChar(THIS_ pszItf, Buffer, OLE_BUF_SIZ, cp);
+		OLECHAR *pBuffer = GetWideChar(aTHX_ pszItf, Buffer, OLE_BUF_SIZ, cp);
 		hr = IIDFromString(pBuffer, &iid);
-		ReleaseBuffer(THIS_ pBuffer, Buffer);
+		ReleaseBuffer(aTHX_ pBuffer, Buffer);
 	    }
 	}
     }
     else
-	hr = FindDefaultSource(THIS_ pObj, &iid, &pTypeInfo, cp, lcid);
+	hr = FindDefaultSource(aTHX_ pObj, &iid, &pTypeInfo, cp, lcid);
 
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     // Get IConnectionPointContainer interface
@@ -4196,7 +4197,7 @@
     DBG(("QueryInterFace(IConnectionPointContainer): hr=0x%08x\n", hr));
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
         XSRETURN_EMPTY;
     }
 
@@ -4208,12 +4209,12 @@
     if (FAILED(hr)) {
 	if (pTypeInfo)
 	    pTypeInfo->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
         XSRETURN_EMPTY;
     }
 
     // Connect our EventSink object to it
-    pObj->pEventSink = new EventSink(THIS_ pObj, handler, iid, pTypeInfo);
+    pObj->pEventSink = new EventSink(aTHX_ pObj, handler, iid, pTypeInfo);
     hr = pObj->pEventSink->Advise(pConnectionPoint);
     pConnectionPoint->Release();
     DBG(("Advise: hr=0x%08x\n", hr));
@@ -4222,7 +4223,7 @@
 	    pTypeInfo->Release();
 	pObj->pEventSink->Release();
 	pObj->pEventSink = NULL;
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
     }
 
  #ifdef _DEBUG
@@ -4249,7 +4250,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self, TRUE);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self, TRUE);
     DBG(("Win32::OLE::Tie::DESTROY |%lx| |%lx|\n", pObj,
 	 pObj ? pObj->pDispatch : NULL));
 
@@ -4261,12 +4262,12 @@
 		/* make sure the reference to the tied hash is still valid */
 		sv_unmagic((SV*)pObj->self, 'P');
 		sv_magic((SV*)pObj->self, self, 'P', Nullch, 0);
-		ReleasePerlObject(THIS_ pObj);
+		ReleasePerlObject(aTHX_ pObj);
 	    }
 	    /* untie hash because we free the object *right now* */
 	    sv_unmagic((SV*)pObj->self, 'P');
 	}
-	RemoveFromObjectChain(THIS_ (OBJECTHEADER*)pObj);
+	RemoveFromObjectChain(aTHX_ (OBJECTHEADER*)pObj);
 	Safefree(pObj);
     }
     DBG(("End of Win32::OLE::Tie::DESTROY\n"));
@@ -4297,37 +4298,37 @@
 	XSRETURN(1);
     }
 
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self);
     DBG(("Win32::OLE::Tie::Fetch(0x%08x,'%s')\n", pObj, buffer));
     if (!pObj)
 	XSRETURN_EMPTY;
 
     HV *stash = SvSTASH(pObj->self);
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
     ST(0) = &PL_sv_undef;
     VariantInit(&result);
     VariantInit(&propName);
 
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
     dispParams.cArgs = 0;
     dispParams.rgvarg = NULL;
     dispParams.cNamedArgs = 0;
     dispParams.rgdispidNamedArgs = NULL;
 
-    hr = GetHashedDispID(THIS_ pObj, buffer, length, dispID, lcid, cp);
+    hr = GetHashedDispID(aTHX_ pObj, buffer, length, dispID, lcid, cp);
     if (FAILED(hr)) {
 	if (!SvTRUE(def)) {
 	    SV *err = newSVpvf(" in GetIDsOfNames \"%s\"", buffer);
-	    ReportOleError(THIS_ stash, hr, NULL, sv_2mortal(err));
+	    ReportOleError(aTHX_ stash, hr, NULL, sv_2mortal(err));
 	    XSRETURN(1);
 	}
 
 	/* default method call: $self->{Key} ---> $self->Item('Key') */
 	V_VT(&propName) = VT_BSTR;
-	V_BSTR(&propName) = AllocOleString(THIS_ buffer, length, cp);
+	V_BSTR(&propName) = AllocOleString(aTHX_ buffer, length, cp);
 	dispParams.cArgs = 1;
 	dispParams.rgvarg = &propName;
     }
@@ -4343,13 +4344,13 @@
 	SV *sv = sv_newmortal();
 	sv_setpvf(sv, "in METHOD/PROPERTYGET \"%s\"", buffer);
 	VariantClear(&result);
-	ReportOleError(THIS_ stash, hr, &excepinfo, sv);
+	ReportOleError(aTHX_ stash, hr, &excepinfo, sv);
     }
     else {
 	ST(0) = sv_newmortal();
-	hr = SetSVFromVariantEx(THIS_ &result, ST(0), stash);
+	hr = SetSVFromVariantEx(aTHX_ &result, ST(0), stash);
 	VariantClear(&result);
-	CheckOleError(THIS_ stash, hr);
+	CheckOleError(aTHX_ stash, hr);
     }
 
     XSRETURN(1);
@@ -4375,15 +4376,15 @@
     VARIANTARG propertyValue[2];
     SV *err = NULL;
 
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     HV *stash = SvSTASH(pObj->self);
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
-    LCID lcid = QueryPkgVar(THIS_ stash, LCID_NAME, LCID_LEN, lcidDefault);
-    UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+    LCID lcid = QueryPkgVar(aTHX_ stash, LCID_NAME, LCID_LEN, lcidDefault);
+    UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
     dispParams.rgdispidNamedArgs = &dispIDParam;
     dispParams.rgvarg = propertyValue;
@@ -4395,20 +4396,20 @@
     Zero(&excepinfo, 1, EXCEPINFO);
 
     buffer = SvPV(key, length);
-    hr = GetHashedDispID(THIS_ pObj, buffer, length, dispID, lcid, cp);
+    hr = GetHashedDispID(aTHX_ pObj, buffer, length, dispID, lcid, cp);
     if (FAILED(hr)) {
 	if (!SvTRUE(def)) {
 	    SV *err = newSVpvf(" in GetIDsOfNames \"%s\"", buffer);
-	    ReportOleError(THIS_ stash, hr, NULL, sv_2mortal(err));
+	    ReportOleError(aTHX_ stash, hr, NULL, sv_2mortal(err));
 	    XSRETURN_EMPTY;
 	}
 
 	dispParams.cArgs = 2;
 	V_VT(&propertyValue[1]) = VT_BSTR;
-	V_BSTR(&propertyValue[1]) = AllocOleString(THIS_ buffer, length, cp);
+	V_BSTR(&propertyValue[1]) = AllocOleString(aTHX_ buffer, length, cp);
     }
 
-    hr = SetVariantFromSVEx(THIS_ value, &propertyValue[0], cp, lcid);
+    hr = SetVariantFromSVEx(aTHX_ value, &propertyValue[0], cp, lcid);
     if (SUCCEEDED(hr)) {
 	USHORT wFlags = DISPATCH_PROPERTYPUT;
 
@@ -4429,7 +4430,7 @@
     for(index = 0; index < dispParams.cArgs; ++index)
 	VariantClear(&propertyValue[index]);
 
-    if (CheckOleError(THIS_ stash, hr, &excepinfo, err))
+    if (CheckOleError(aTHX_ stash, hr, &excepinfo, err))
 	XSRETURN_EMPTY;
 
     XSRETURN_YES;
@@ -4445,7 +4446,7 @@
 PPCODE:
 {
     /* NEXTKEY has an additional "lastkey" arg, which is not needed here */
-    WINOLEOBJECT *pObj = GetOleObject(THIS_ self);
+    WINOLEOBJECT *pObj = GetOleObject(aTHX_ self);
     char *paszMethod[] = {"FIRSTKEY", "NEXTKEY", "FIRSTENUM", "NEXTENUM"};
 
     DBG(("%s called, pObj=%p\n", paszMethod[ix], pObj));
@@ -4453,22 +4454,22 @@
 	XSRETURN_EMPTY;
 
     HV *stash = SvSTASH(pObj->self);
-    SetLastOleError(THIS_ stash);
+    SetLastOleError(aTHX_ stash);
 
     switch (ix) {
     case 0: /* FIRSTKEY */
-	FetchTypeInfo(THIS_ pObj);
+	FetchTypeInfo(aTHX_ pObj);
 	pObj->PropIndex = 0;
     case 1: /* NEXTKEY */
-	ST(0) = NextPropertyName(THIS_ pObj);
+	ST(0) = NextPropertyName(aTHX_ pObj);
 	break;
 
     case 2: /* FIRSTENUM */
 	if (pObj->pEnum)
 	    pObj->pEnum->Release();
-	pObj->pEnum = CreateEnumVARIANT(THIS_ pObj);
+	pObj->pEnum = CreateEnumVARIANT(aTHX_ pObj);
     case 3: /* NEXTENUM */
-	ST(0) = NextEnumElement(THIS_ pObj->pEnum, stash);
+	ST(0) = NextEnumElement(aTHX_ pObj->pEnum, stash);
 	if (!SvOK(ST(0))) {
 	    pObj->pEnum->Release();
 	    pObj->pEnum = NULL;
@@ -4507,35 +4508,35 @@
     HV *stash = gv_stashpv(szWINOLE, TRUE);
     unsigned int count;
 
-    Initialize(THIS_ stash);
-    SetLastOleError(THIS_ stash);
+    Initialize(aTHX_ stash);
+    SetLastOleError(aTHX_ stash);
 
     char *pszBuffer = SvPV_nolen(classid);
-    pBuffer = GetWideChar(THIS_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
+    pBuffer = GetWideChar(aTHX_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
     hr = CLSIDFromString(pBuffer, &clsid);
-    ReleaseBuffer(THIS_ pBuffer, Buffer);
-    if (CheckOleError(THIS_ stash, hr))
+    ReleaseBuffer(aTHX_ pBuffer, Buffer);
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     hr = LoadRegTypeLib(clsid, major, minor, lcid, &pTypeLib);
     if (FAILED(hr) && SvPOK(typelib)) {
 	/* typelib not registerd, try to read from file "typelib" */
 	pszBuffer = SvPV_nolen(typelib);
-	pBuffer = GetWideChar(THIS_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
+	pBuffer = GetWideChar(aTHX_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
 	hr = LoadTypeLibEx(pBuffer, REGKIND_NONE, &pTypeLib);
-	ReleaseBuffer(THIS_ pBuffer, Buffer);
+	ReleaseBuffer(aTHX_ pBuffer, Buffer);
     }
-    if (CheckOleError(THIS_ stash, hr))
+    if (CheckOleError(aTHX_ stash, hr))
 	XSRETURN_EMPTY;
 
     hr = pTypeLib->GetLibAttr(&pTLibAttr);
     if (FAILED(hr)) {
 	pTypeLib->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeLibObject(THIS_ pTypeLib, pTLibAttr));
+    ST(0) = sv_2mortal(CreateTypeLibObject(aTHX_ pTypeLib, pTLibAttr));
     XSRETURN(1);
 }
 
@@ -4551,7 +4552,7 @@
     HV *hv;
     unsigned int count;
 
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ typelib);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ typelib);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -4573,13 +4574,13 @@
 	TYPEATTR  *pTypeAttr;
 
 	hr = pObj->pTypeLib->GetTypeInfo(index, &pTypeInfo);
-	if (CheckOleError(THIS_ stash, hr))
+	if (CheckOleError(aTHX_ stash, hr))
 	    continue;
 
 	hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
 	if (FAILED(hr)) {
 	    pTypeInfo->Release();
-	    ReportOleError(THIS_ stash, hr);
+	    ReportOleError(aTHX_ stash, hr);
 	    continue;
 	}
 
@@ -4588,7 +4589,7 @@
 
 	    hr = pTypeInfo->GetVarDesc(iVar, &pVarDesc);
 	    /* XXX LEAK alert */
-	    if (CheckOleError(THIS_ stash, hr))
+	    if (CheckOleError(aTHX_ stash, hr))
 	        continue;
 
 	    if (pVarDesc->varkind == VAR_CONST &&
@@ -4601,15 +4602,15 @@
 		char szName[64];
 
 		hr = pTypeInfo->GetNames(pVarDesc->memid, &bstr, 1, &cName);
-		if (CheckOleError(THIS_ stash, hr) || cName == 0 || !bstr)
+		if (CheckOleError(aTHX_ stash, hr) || cName == 0 || !bstr)
 		    continue;
 
-		char *pszName = GetMultiByte(THIS_ bstr,
+		char *pszName = GetMultiByte(aTHX_ bstr,
 					     szName, sizeof(szName), cp);
 		SV *sv = newSV(0);
 		/* XXX LEAK alert */
-		hr = SetSVFromVariantEx(THIS_ pVarDesc->lpvarValue, sv, stash);
-		if (!CheckOleError(THIS_ stash, hr)) {
+		hr = SetSVFromVariantEx(aTHX_ pVarDesc->lpvarValue, sv, stash);
+		if (!CheckOleError(aTHX_ stash, hr)) {
 		    if (SvOK(caller)) {
 			/* XXX check for valid symbol name */
 			newCONSTSUB(hv, pszName, sv);
@@ -4618,7 +4619,7 @@
 		        hv_store(hv, pszName, strlen(pszName), sv, 0);
 		}
 		SysFreeString(bstr);
-		ReleaseBuffer(THIS_ pszName, szName);
+		ReleaseBuffer(aTHX_ pszName, szName);
 	    }
 	    pTypeInfo->ReleaseVarDesc(pVarDesc);
 	}
@@ -4638,7 +4639,12 @@
     FILETIME ft;
     LONG err;
 
-    err = RegOpenKeyEx(HKEY_CLASSES_ROOT, "Typelib", 0, KEY_READ, &hKeyTypelib);
+    if (USING_WIDE()) {
+	err = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Typelib", 0, KEY_READ, &hKeyTypelib);
+    }
+    else {
+	err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Typelib", 0, KEY_READ, &hKeyTypelib);
+    }
     if (err != ERROR_SUCCESS) {
 	warn("Cannot access HKEY_CLASSES_ROOT\\Typelib");
 	XSRETURN_EMPTY;
@@ -4648,47 +4654,106 @@
 
     // Enumerate all Clsids
     for (DWORD dwClsid=0;; ++dwClsid) {
-	char szClsid[100];
-	DWORD cbClsid = sizeof(szClsid);
-	err = RegEnumKeyEx(hKeyTypelib, dwClsid, szClsid, &cbClsid,
-			   NULL, NULL, NULL, &ft);
-	if (err != ERROR_SUCCESS)
-	    break;
-
 	HKEY hKeyClsid;
-	err = RegOpenKeyEx(hKeyTypelib, szClsid, 0, KEY_READ, &hKeyClsid);
-	if (err != ERROR_SUCCESS)
-	    continue;
+	char szClsid[200];
+	WCHAR wClsid[100];
+	DWORD cbClsid;
+	if (USING_WIDE()) {
+	    cbClsid = (sizeof(wClsid)/sizeof(wClsid[0]));
+	    err = RegEnumKeyExW(hKeyTypelib, dwClsid, wClsid, &cbClsid,
+			       NULL, NULL, NULL, &ft);
+	    if (err != ERROR_SUCCESS)
+		break;
 
-	// Enumerate versions for current clsid
-	for (DWORD dwVersion=0;; ++dwVersion) {
-	    char szVersion[10];
-	    DWORD cbVersion = sizeof(szVersion);
-	    err = RegEnumKeyEx(hKeyClsid, dwVersion, szVersion, &cbVersion,
+	    err = RegOpenKeyExW(hKeyTypelib, wClsid, 0, KEY_READ, &hKeyClsid);
+	    if (err != ERROR_SUCCESS)
+    		continue;
+
+	    W2AHELPER(wClsid, szClsid, sizeof(szClsid));
+	    cbClsid = strlen(szClsid);
+	}
+	else {
+	    cbClsid = (sizeof(szClsid)/sizeof(szClsid[0]));
+	    err = RegEnumKeyExA(hKeyTypelib, dwClsid, szClsid, &cbClsid,
 			       NULL, NULL, NULL, &ft);
 	    if (err != ERROR_SUCCESS)
 		break;
 
-	    HKEY hKeyVersion;
-	    err = RegOpenKeyEx(hKeyClsid, szVersion, 0, KEY_READ, &hKeyVersion);
+	    err = RegOpenKeyExA(hKeyTypelib, szClsid, 0, KEY_READ, &hKeyClsid);
 	    if (err != ERROR_SUCCESS)
 		continue;
+	}
 
-	    char szTitle[300];
-	    LONG cbTitle = sizeof(szTitle);
-	    err = RegQueryValue(hKeyVersion, NULL, szTitle, &cbTitle);
-	    if (err != ERROR_SUCCESS || cbTitle <= 1)
-		continue;
+	// Enumerate versions for current clsid
+	for (DWORD dwVersion=0;; ++dwVersion) {
+	    HKEY hKeyVersion;
+	    char szVersion[20];
+	    char szTitle[600];
+	    WCHAR wVersion[10];
+	    WCHAR wTitle[300];
+	    DWORD cbVersion;
+	    LONG cbTitle;
+	    if (USING_WIDE()) {
+		cbVersion = (sizeof(wVersion)/sizeof(wVersion[0]));
+		err = RegEnumKeyExW(hKeyClsid, dwVersion, wVersion, &cbVersion,
+				   NULL, NULL, NULL, &ft);
+		if (err != ERROR_SUCCESS)
+		    break;
 
-	    // Enumerate languages
-	    for (DWORD dwLangid=0;; ++dwLangid) {
-		char szLangid[10];
-		DWORD cbLangid = sizeof(szLangid);
-		err = RegEnumKeyEx(hKeyVersion, dwLangid, szLangid, &cbLangid,
+		err = RegOpenKeyExW(hKeyClsid, wVersion, 0, KEY_READ, &hKeyVersion);
+		if (err != ERROR_SUCCESS)
+		    continue;
+		
+		cbTitle = (sizeof(wTitle)/sizeof(wTitle[0]));
+		err = RegQueryValueW(hKeyVersion, NULL, wTitle, &cbTitle);
+		if (err != ERROR_SUCCESS || cbTitle <= 1)
+		    continue;
+
+		W2AHELPER(wVersion, szVersion, sizeof(szVersion));
+		cbVersion = strlen(szVersion);
+		W2AHELPER(wTitle, szTitle, sizeof(szTitle));
+		cbTitle = strlen(szTitle);
+	    }
+	    else {
+		cbVersion = (sizeof(szVersion)/sizeof(szVersion[0]));
+		err = RegEnumKeyExA(hKeyClsid, dwVersion, szVersion, &cbVersion,
 				   NULL, NULL, NULL, &ft);
 		if (err != ERROR_SUCCESS)
 		    break;
 
+		err = RegOpenKeyExA(hKeyClsid, szVersion, 0, KEY_READ, &hKeyVersion);
+		if (err != ERROR_SUCCESS)
+		    continue;
+
+		cbTitle = (sizeof(szTitle)/sizeof(szTitle[0]));
+		err = RegQueryValueA(hKeyVersion, NULL, szTitle, &cbTitle);
+		if (err != ERROR_SUCCESS || cbTitle <= 1)
+		    continue;
+	    }
+
+	    // Enumerate languages
+	    for (DWORD dwLangid=0;; ++dwLangid) {
+		char szLangid[20];
+		WCHAR wLangid[10];
+		DWORD cbLangid;
+		if (USING_WIDE()) {
+		    cbLangid = (sizeof(wLangid)/sizeof(wLangid[0]));
+		    err = RegEnumKeyExW(hKeyVersion, dwLangid, wLangid, &cbLangid,
+				       NULL, NULL, NULL, &ft);
+		    if (err != ERROR_SUCCESS)
+			break;
+		    
+		    W2AHELPER(wLangid, szLangid, sizeof(szLangid));
+		    cbLangid = strlen(szLangid);
+		}
+		else {
+		    cbLangid = (sizeof(szLangid)/sizeof(szLangid[0]));
+		    err = RegEnumKeyExA(hKeyVersion, dwLangid, szLangid, &cbLangid,
+				       NULL, NULL, NULL, &ft);
+		    if (err != ERROR_SUCCESS)
+			break;
+		}
+
 		// Language ids must be strictly numeric
 		char *psz=szLangid;
 		while (isDIGIT(*psz))
@@ -4697,15 +4762,34 @@
 		    continue;
 
 		HKEY hKeyLangid;
-		err = RegOpenKeyEx(hKeyVersion, szLangid, 0, KEY_READ,
-				   &hKeyLangid);
-		if (err != ERROR_SUCCESS)
-		    continue;
+		if (USING_WIDE()) {
+		    // wLangid is still valid
+		    err = RegOpenKeyExW(hKeyVersion, wLangid, 0, KEY_READ,
+				       &hKeyLangid);
+		    if (err != ERROR_SUCCESS)
+			continue;
+		}
+		else {
+		    err = RegOpenKeyExA(hKeyVersion, szLangid, 0, KEY_READ,
+				       &hKeyLangid);
+		    if (err != ERROR_SUCCESS)
+			continue;
+		}
 
 		// Retrieve filename of type library
 		char szFile[MAX_PATH+1];
+		WCHAR wFile[MAX_PATH+1];
 		LONG cbFile = sizeof(szFile);
-		err = RegQueryValue(hKeyLangid, "win32", szFile, &cbFile);
+		if (USING_WIDE()) {
+		    cbFile = (sizeof(wFile)/sizeof(wFile[0]));
+		    err = RegQueryValueW(hKeyLangid, L"win32", wFile, &cbFile);
+		    W2AHELPER(wFile, szFile, sizeof(szFile));
+		    cbFile = strlen(szFile)+1;
+		}
+		else {
+		    cbFile = (sizeof(szFile)/sizeof(szFile[0]));
+		    err = RegQueryValueA(hKeyLangid, "win32", szFile, &cbFile);
+		}
 		if (err == ERROR_SUCCESS && cbFile > 1) {
 		    AV *av = newAV();
 		    av_push(av, newSVpv(szClsid, cbClsid));
@@ -4771,21 +4855,21 @@
     New(0, pEnumObj, 1, WINOLEENUMOBJECT);
 
     if (ix == 0) { /* new */
-	WINOLEOBJECT *pObj = GetOleObject(THIS_ object);
+	WINOLEOBJECT *pObj = GetOleObject(aTHX_ object);
 	if (pObj) {
-	    HV *olestash = GetWin32OleStash(THIS_ object);
-	    SetLastOleError(THIS_ olestash);
-	    pEnumObj->pEnum = CreateEnumVARIANT(THIS_ pObj);
+	    HV *olestash = GetWin32OleStash(aTHX_ object);
+	    SetLastOleError(aTHX_ olestash);
+	    pEnumObj->pEnum = CreateEnumVARIANT(aTHX_ pObj);
 	}
     }
     else { /* Clone */
-	WINOLEENUMOBJECT *pOriginal = GetOleEnumObject(THIS_ self);
+	WINOLEENUMOBJECT *pOriginal = GetOleEnumObject(aTHX_ self);
 	if (pOriginal) {
-	    HV *olestash = GetWin32OleStash(THIS_ self);
-	    SetLastOleError(THIS_ olestash);
+	    HV *olestash = GetWin32OleStash(aTHX_ self);
+	    SetLastOleError(aTHX_ olestash);
 
 	    HRESULT hr = pOriginal->pEnum->Clone(&pEnumObj->pEnum);
-	    CheckOleError(THIS_ olestash, hr);
+	    CheckOleError(aTHX_ olestash, hr);
 	}
     }
 
@@ -4794,10 +4878,10 @@
 	XSRETURN_EMPTY;
     }
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pEnumObj, WINOLEENUM_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pEnumObj, WINOLEENUM_MAGIC);
 
     SV *sv = newSViv((IV)pEnumObj);
-    ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), GetStash(THIS_ self)));
+    ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), GetStash(aTHX_ self)));
     XSRETURN(1);
 }
 
@@ -4806,9 +4890,9 @@
     SV *self
 PPCODE:
 {
-    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(THIS_ self, TRUE);
+    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(aTHX_ self, TRUE);
     if (pEnumObj) {
-	RemoveFromObjectChain(THIS_ (OBJECTHEADER*)pEnumObj);
+	RemoveFromObjectChain(aTHX_ (OBJECTHEADER*)pEnumObj);
 	if (pEnumObj->pEnum)
 	    pEnumObj->pEnum->Release();
 	Safefree(pEnumObj);
@@ -4851,16 +4935,16 @@
 	}
     }
 
-    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(THIS_ self);
+    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(aTHX_ self);
     if (!pEnumObj)
 	XSRETURN_EMPTY;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     SV *sv = NULL;
     while (ix == 0 || count-- > 0) {
-	sv = NextEnumElement(THIS_ pEnumObj->pEnum, olestash);
+	sv = NextEnumElement(aTHX_ pEnumObj->pEnum, olestash);
 	if (!SvOK(sv))
 	    break;
 	if (!SvIMMORTAL(sv))
@@ -4878,15 +4962,15 @@
     SV *self
 PPCODE:
 {
-    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(THIS_ self);
+    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(aTHX_ self);
     if (!pEnumObj)
 	XSRETURN_NO;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     HRESULT hr = pEnumObj->pEnum->Reset();
-    CheckOleError(THIS_ olestash, hr);
+    CheckOleError(aTHX_ olestash, hr);
     ST(0) = boolSV(hr == S_OK);
     XSRETURN(1);
 }
@@ -4896,15 +4980,15 @@
     SV *self
 PPCODE:
 {
-    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(THIS_ self);
+    WINOLEENUMOBJECT *pEnumObj = GetOleEnumObject(aTHX_ self);
     if (!pEnumObj)
 	XSRETURN_NO;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
     int count = (items > 1) ? SvIV(ST(1)) : 1;
     HRESULT hr = pEnumObj->pEnum->Skip(count);
-    CheckOleError(THIS_ olestash, hr);
+    CheckOleError(aTHX_ olestash, hr);
     ST(0) = boolSV(hr == S_OK);
     XSRETURN(1);
 }
@@ -4925,8 +5009,8 @@
 
     // XXX Initialize should be superfluous here
     // Initialize();
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     VARTYPE vt_base = vt & VT_TYPEMASK;
     if (!data && vt_base != VT_NULL && vt_base != VT_EMPTY &&
@@ -5007,7 +5091,7 @@
 	    hr = SafeArrayAccessData(V_ARRAY(pVariant), (void**)&pDest);
 	    if (FAILED(hr)) {
 		VariantClear(pVariant);
-		ReportOleError(THIS_ olestash, hr);
+		ReportOleError(aTHX_ olestash, hr);
 	    }
 	    else {
 		memcpy(pDest, ptr, len);
@@ -5016,20 +5100,20 @@
 	}
     }
     else {
-	UINT cp = QueryPkgVar(THIS_ olestash, CP_NAME, CP_LEN, cpDefault);
-	LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN,
+	UINT cp = QueryPkgVar(aTHX_ olestash, CP_NAME, CP_LEN, cpDefault);
+	LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN,
 				lcidDefault);
-	hr = AssignVariantFromSV(THIS_ data, pVariant, cp, lcid);
+	hr = AssignVariantFromSV(aTHX_ data, pVariant, cp, lcid);
 	if (FAILED(hr)) {
 	    Safefree(pVarObj);
-	    ReportOleError(THIS_ olestash, hr);
+	    ReportOleError(aTHX_ olestash, hr);
 	    XSRETURN_EMPTY;
 	}
     }
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pVarObj, WINOLEVARIANT_MAGIC);
 
-    HV *stash = GetStash(THIS_ self);
+    HV *stash = GetStash(aTHX_ self);
     SV *sv = newSViv((IV)pVarObj);
     ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), stash));
     XSRETURN(1);
@@ -5040,9 +5124,9 @@
     SV *self
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (pVarObj) {
-	RemoveFromObjectChain(THIS_ (OBJECTHEADER*)pVarObj);
+	RemoveFromObjectChain(aTHX_ (OBJECTHEADER*)pVarObj);
 	VariantClear(&pVarObj->byref);
 	VariantClear(&pVarObj->variant);
 	Safefree(pVarObj);
@@ -5057,32 +5141,32 @@
     IV type
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
     HRESULT hr;
     VARIANT variant;
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
 
     ST(0) = &PL_sv_undef;
-    SetLastOleError(THIS_ olestash);
+    SetLastOleError(aTHX_ olestash);
     VariantInit(&variant);
     hr = VariantChangeTypeEx(&variant, &pVarObj->variant, lcid, 0, type);
     if (SUCCEEDED(hr)) {
 	ST(0) = sv_newmortal();
-	hr = SetSVFromVariantEx(THIS_ &variant, ST(0), olestash);
+	hr = SetSVFromVariantEx(aTHX_ &variant, ST(0), olestash);
     }
     else if (V_VT(&pVarObj->variant) == VT_ERROR) {
 	/* special handling for VT_ERROR */
 	ST(0) = sv_newmortal();
 	V_VT(&variant) = VT_I4;
 	V_I4(&variant) = V_ERROR(&pVarObj->variant);
-	hr = SetSVFromVariantEx(THIS_ &variant, ST(0), olestash, FALSE);
+	hr = SetSVFromVariantEx(aTHX_ &variant, ST(0), olestash, FALSE);
     }
     VariantClear(&variant);
-    CheckOleError(THIS_ olestash, hr);
+    CheckOleError(aTHX_ olestash, hr);
     XSRETURN(1);
 }
 
@@ -5092,19 +5176,19 @@
     IV type
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
     HRESULT hr = E_INVALIDARG;
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
 
-    SetLastOleError(THIS_ olestash);
+    SetLastOleError(aTHX_ olestash);
     /* XXX: Does it work with VT_BYREF? */
     hr = VariantChangeTypeEx(&pVarObj->variant, &pVarObj->variant,
 			     lcid, 0, type);
-    CheckOleError(THIS_ olestash, hr);
+    CheckOleError(aTHX_ olestash, hr);
     if (FAILED(hr))
 	ST(0) = &PL_sv_undef;
 
@@ -5118,12 +5202,12 @@
     _Clone = 1
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
     HRESULT hr;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
 
     VARIANT *pSource = &pVarObj->variant;
     VARIANT variant, byref;
@@ -5169,7 +5253,7 @@
 
 	hr = SafeArrayGetElement(psa, rgIndices, V_BYREF(&variant));
 	Safefree(rgIndices);
-	if (CheckOleError(THIS_ olestash, hr))
+	if (CheckOleError(aTHX_ olestash, hr))
 	    XSRETURN_EMPTY;
 	pSource = &variant;
     }
@@ -5187,13 +5271,13 @@
     VariantClear(&byref);
     if (FAILED(hr)) {
 	Safefree(pNewVar);
-	ReportOleError(THIS_ olestash, hr);
+	ReportOleError(aTHX_ olestash, hr);
 	XSRETURN_EMPTY;
     }
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pNewVar, WINOLEVARIANT_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pNewVar, WINOLEVARIANT_MAGIC);
 
-    HV *stash = GetStash(THIS_ self);
+    HV *stash = GetStash(aTHX_ self);
     SV *sv = newSViv((IV)pNewVar);
     ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), stash));
     XSRETURN(1);
@@ -5206,7 +5290,7 @@
     Time = 1
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
@@ -5217,8 +5301,8 @@
 	XSRETURN_EMPTY;
     }
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     char *fmt = NULL;
     DWORD dwFlags = 0;
@@ -5233,39 +5317,72 @@
     if (items > 2)
 	lcid = SvIV(ST(2));
     else
-	lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
+	lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
 
     HRESULT hr;
     VARIANT variant;
     VariantInit(&variant);
     hr = VariantChangeTypeEx(&variant, &pVarObj->variant, lcid, 0, VT_DATE);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
         XSRETURN_EMPTY;
 
     SYSTEMTIME systime;
     VariantTimeToSystemTime(V_DATE(&variant), &systime);
 
+    WCHAR* wFmt = NULL;
     int len;
-    if (ix == 0)
-	len = GetDateFormatA(lcid, dwFlags, &systime, fmt, NULL, 0);
-    else
-	len = GetTimeFormatA(lcid, dwFlags, &systime, fmt, NULL, 0);
+    if (USING_WIDE()) {
+	if(fmt) {
+	    len = strlen(fmt)+1;
+	    New(0, wFmt, len, WCHAR);
+	    A2WHELPER(fmt, wFmt, len*sizeof(WCHAR));
+	}
 
-    if (len > 1) {
-	SV *sv = ST(0) = sv_2mortal(newSV(len));
+	if (ix == 0)
+	    len = GetDateFormatW(lcid, dwFlags, &systime, wFmt, NULL, 0);
+	else
+	    len = GetTimeFormatW(lcid, dwFlags, &systime, wFmt, NULL, 0);
+    }
+    else {
 	if (ix == 0)
-	    len = GetDateFormatA(lcid, dwFlags, &systime, fmt, SvPVX(sv), len);
+	    len = GetDateFormatA(lcid, dwFlags, &systime, fmt, NULL, 0);
 	else
-	    len = GetTimeFormatA(lcid, dwFlags, &systime, fmt, SvPVX(sv), len);
+	    len = GetTimeFormatA(lcid, dwFlags, &systime, fmt, NULL, 0);
+    }
+    if (len > 1) {
+	if (USING_WIDE()) {
+	    WCHAR* wInfo;
+	    char* pInfo;
+	    New(0, wInfo, len+1, WCHAR);
+	    if (ix == 0)
+		len = GetDateFormatW(lcid, dwFlags, &systime, wFmt, wInfo, len);
+	    else
+		len = GetTimeFormatW(lcid, dwFlags, &systime, wFmt, wInfo, len);
+	    New(0, pInfo, (len+1)*2, char);
+	    W2AHELPER(wInfo, pInfo, (len+1)*2);
+	    ST(0) = sv_2mortal(newSVpv(pInfo, 0));
+	    Safefree(pInfo);
+	    Safefree(wInfo);
+	}
+	else {
+	    SV *sv = ST(0) = sv_2mortal(newSV(len));
+	    if (ix == 0)
+		len = GetDateFormatA(lcid, dwFlags, &systime, fmt, SvPVX(sv), len);
+	    else
+		len = GetTimeFormatA(lcid, dwFlags, &systime, fmt, SvPVX(sv), len);
 
-	if (len > 1) {
-	    SvCUR_set(sv, len-1);
-	    SvPOK_on(sv);
+	    if (len > 1) {
+		SvCUR_set(sv, len-1);
+		SvPOK_on(sv);
+	    }
 	}
     }
     else
         ST(0) = &PL_sv_undef;
 
+    if(wFmt)
+	Safefree(wFmt);
+
     VariantClear(&variant);
     XSRETURN(1);
 }
@@ -5275,7 +5392,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
@@ -5285,8 +5402,8 @@
 	XSRETURN_EMPTY;
     }
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     HV *hv = NULL;
     DWORD dwFlags = 0;
@@ -5308,35 +5425,59 @@
     if (items > 2)
 	lcid = SvIV(ST(2));
     else
-	lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
+	lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
 
     HRESULT hr;
     VARIANT variant;
     VariantInit(&variant);
     hr = VariantChangeTypeEx(&variant, &pVarObj->variant, lcid, 0, VT_CY);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
-    CURRENCYFMT fmt;
-    Zero(&fmt, 1, CURRENCYFMT);
+    CURRENCYFMTA afmt;
+    CURRENCYFMTW wfmt;
+    if (USING_WIDE()) {
+        Zero(&wfmt, 1, CURRENCYFMTW);
+
+	wfmt.NumDigits        = GetLocaleNumber(aTHX_ hv, "NumDigits",
+					       lcid, LOCALE_IDIGITS);
+	wfmt.LeadingZero      = GetLocaleNumber(aTHX_ hv, "LeadingZero",
+					       lcid, LOCALE_ILZERO);
+	wfmt.Grouping         = GetLocaleNumber(aTHX_ hv, "Grouping",
+					       lcid, LOCALE_SMONGROUPING);
+	wfmt.NegativeOrder    = GetLocaleNumber(aTHX_ hv, "NegativeOrder",
+					       lcid, LOCALE_INEGCURR);
+	wfmt.PositiveOrder    = GetLocaleNumber(aTHX_ hv, "PositiveOrder",
+					       lcid, LOCALE_ICURRENCY);
+
+	wfmt.lpDecimalSep     = GetLocaleStringW(aTHX_ hv, "DecimalSep",
+					       lcid, LOCALE_SMONDECIMALSEP);
+	wfmt.lpThousandSep    = GetLocaleStringW(aTHX_ hv, "ThousandSep",
+					       lcid, LOCALE_SMONTHOUSANDSEP);
+	wfmt.lpCurrencySymbol = GetLocaleStringW(aTHX_ hv, "CurrencySymbol",
+					       lcid, LOCALE_SCURRENCY);
+    }
+    else {
+	Zero(&afmt, 1, CURRENCYFMTA);
 
-    fmt.NumDigits        = GetLocaleNumber(THIS_ hv, "NumDigits",
-					   lcid, LOCALE_IDIGITS);
-    fmt.LeadingZero      = GetLocaleNumber(THIS_ hv, "LeadingZero",
-					   lcid, LOCALE_ILZERO);
-    fmt.Grouping         = GetLocaleNumber(THIS_ hv, "Grouping",
-					   lcid, LOCALE_SMONGROUPING);
-    fmt.NegativeOrder    = GetLocaleNumber(THIS_ hv, "NegativeOrder",
-					   lcid, LOCALE_INEGCURR);
-    fmt.PositiveOrder    = GetLocaleNumber(THIS_ hv, "PositiveOrder",
-					   lcid, LOCALE_ICURRENCY);
-
-    fmt.lpDecimalSep     = GetLocaleString(THIS_ hv, "DecimalSep",
-					   lcid, LOCALE_SMONDECIMALSEP);
-    fmt.lpThousandSep    = GetLocaleString(THIS_ hv, "ThousandSep",
-					   lcid, LOCALE_SMONTHOUSANDSEP);
-    fmt.lpCurrencySymbol = GetLocaleString(THIS_ hv, "CurrencySymbol",
-					   lcid, LOCALE_SCURRENCY);
+	afmt.NumDigits        = GetLocaleNumber(aTHX_ hv, "NumDigits",
+					       lcid, LOCALE_IDIGITS);
+	afmt.LeadingZero      = GetLocaleNumber(aTHX_ hv, "LeadingZero",
+					       lcid, LOCALE_ILZERO);
+	afmt.Grouping         = GetLocaleNumber(aTHX_ hv, "Grouping",
+					       lcid, LOCALE_SMONGROUPING);
+	afmt.NegativeOrder    = GetLocaleNumber(aTHX_ hv, "NegativeOrder",
+					       lcid, LOCALE_INEGCURR);
+	afmt.PositiveOrder    = GetLocaleNumber(aTHX_ hv, "PositiveOrder",
+					       lcid, LOCALE_ICURRENCY);
+
+	afmt.lpDecimalSep     = GetLocaleString(aTHX_ hv, "DecimalSep",
+					       lcid, LOCALE_SMONDECIMALSEP);
+	afmt.lpThousandSep    = GetLocaleString(aTHX_ hv, "ThousandSep",
+					       lcid, LOCALE_SMONTHOUSANDSEP);
+	afmt.lpCurrencySymbol = GetLocaleString(aTHX_ hv, "CurrencySymbol",
+					       lcid, LOCALE_SCURRENCY);
+    }
 
     int len = 0;
     int sign = 0;
@@ -5368,19 +5509,45 @@
     DBG(("amount='%s' number='%s' len=%d sign=%d", amount, SvPVX(number),
 	 len, sign));
 
-    len = GetCurrencyFormatA(lcid, dwFlags, SvPVX(number), &fmt, NULL, 0);
+    WCHAR* wNumber = NULL;
+    char* pNumber = SvPVX(number);
+    if (USING_WIDE()) {
+	len = strlen(pNumber)+1;
+	New(0, wNumber, len, WCHAR);
+	A2WHELPER(pNumber, wNumber, len*sizeof(WCHAR));
+	len = GetCurrencyFormatW(lcid, dwFlags, wNumber, &wfmt, NULL, 0);
+    }
+    else {
+	len = GetCurrencyFormatA(lcid, dwFlags, pNumber, &afmt, NULL, 0);
+    }
     if (len > 1) {
-	SV *sv = ST(0) = sv_2mortal(newSV(len));
-	len = GetCurrencyFormatA(lcid, dwFlags, SvPVX(number), &fmt,
-				 SvPVX(sv), len);
-	if (len > 1) {
-	    SvCUR_set(sv, len-1);
-	    SvPOK_on(sv);
+	if (USING_WIDE()) {
+	    WCHAR* wInfo;
+	    char* pInfo;
+	    New(0, wInfo, len+1, WCHAR);
+	    New(0, pInfo, (len+1)*2, char);
+	    len = GetCurrencyFormatW(lcid, dwFlags, wNumber, &wfmt,
+				     wInfo, len);
+	    W2AHELPER(wInfo, pInfo, (len+1)*2);
+	    ST(0) = sv_2mortal(newSVpv(pInfo, 0));
+	    Safefree(pInfo);
+	    Safefree(wInfo);
 	}
+	else {
+	    SV *sv = ST(0) = sv_2mortal(newSV(len));
+	    len = GetCurrencyFormatA(lcid, dwFlags, pNumber, &afmt,
+				     SvPVX(sv), len);
+	    if (len > 1) {
+		SvCUR_set(sv, len-1);
+		SvPOK_on(sv);
+	    }
+	}
     }
     else
 	ST(0) = &PL_sv_undef;
-
+    
+    if(wNumber)
+	Safefree(wNumber);
     SvREFCNT_dec(number);
     VariantClear(&variant);
     XSRETURN(1);
@@ -5391,7 +5558,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
@@ -5401,8 +5568,8 @@
 	XSRETURN_EMPTY;
     }
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    SetLastOleError(THIS_ olestash);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    SetLastOleError(aTHX_ olestash);
 
     HV *hv = NULL;
     DWORD dwFlags = 0;
@@ -5424,46 +5591,97 @@
     if (items > 2)
 	lcid = SvIV(ST(2));
     else
-	lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
+	lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN, lcidDefault);
 
     HRESULT hr;
     VARIANT variant;
     VariantInit(&variant);
     hr = VariantChangeTypeEx(&variant, &pVarObj->variant, lcid, 0, VT_R8);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
-    NUMBERFMT fmt;
-    Zero(&fmt, 1, NUMBERFMT);
+    UINT NumDigits;
+    NUMBERFMTA afmt;
+    NUMBERFMTW wfmt;
+    if (USING_WIDE()) {
+	Zero(&wfmt, 1, NUMBERFMT);
+
+	wfmt.NumDigits     = GetLocaleNumber(aTHX_ hv, "NumDigits",
+					    lcid, LOCALE_IDIGITS);
+	wfmt.LeadingZero   = GetLocaleNumber(aTHX_ hv, "LeadingZero",
+					    lcid, LOCALE_ILZERO);
+	wfmt.Grouping      = GetLocaleNumber(aTHX_ hv, "Grouping",
+					    lcid, LOCALE_SGROUPING);
+	wfmt.NegativeOrder = GetLocaleNumber(aTHX_ hv, "NegativeOrder",
+					    lcid, LOCALE_INEGNUMBER);
+
+	wfmt.lpDecimalSep  = GetLocaleStringW(aTHX_ hv, "DecimalSep",
+					    lcid, LOCALE_SDECIMAL);
+	wfmt.lpThousandSep = GetLocaleStringW(aTHX_ hv, "ThousandSep",
+					    lcid, LOCALE_STHOUSAND);
+	NumDigits = wfmt.NumDigits;
+    }
+    else {
+	Zero(&afmt, 1, NUMBERFMT);
 
-    fmt.NumDigits     = GetLocaleNumber(THIS_ hv, "NumDigits",
-					lcid, LOCALE_IDIGITS);
-    fmt.LeadingZero   = GetLocaleNumber(THIS_ hv, "LeadingZero",
-					lcid, LOCALE_ILZERO);
-    fmt.Grouping      = GetLocaleNumber(THIS_ hv, "Grouping",
-					lcid, LOCALE_SGROUPING);
-    fmt.NegativeOrder = GetLocaleNumber(THIS_ hv, "NegativeOrder",
-					lcid, LOCALE_INEGNUMBER);
-
-    fmt.lpDecimalSep  = GetLocaleString(THIS_ hv, "DecimalSep",
-					lcid, LOCALE_SDECIMAL);
-    fmt.lpThousandSep = GetLocaleString(THIS_ hv, "ThousandSep",
-					lcid, LOCALE_STHOUSAND);
+	afmt.NumDigits     = GetLocaleNumber(aTHX_ hv, "NumDigits",
+					    lcid, LOCALE_IDIGITS);
+	afmt.LeadingZero   = GetLocaleNumber(aTHX_ hv, "LeadingZero",
+					    lcid, LOCALE_ILZERO);
+	afmt.Grouping      = GetLocaleNumber(aTHX_ hv, "Grouping",
+					    lcid, LOCALE_SGROUPING);
+	afmt.NegativeOrder = GetLocaleNumber(aTHX_ hv, "NegativeOrder",
+					    lcid, LOCALE_INEGNUMBER);
+
+	afmt.lpDecimalSep  = GetLocaleString(aTHX_ hv, "DecimalSep",
+					    lcid, LOCALE_SDECIMAL);
+	afmt.lpThousandSep = GetLocaleString(aTHX_ hv, "ThousandSep",
+					    lcid, LOCALE_STHOUSAND);
+	NumDigits = afmt.NumDigits;
+    }
 
-    SV *number = newSVpvf("%.*f", fmt.NumDigits, V_R8(&variant));
-    int len = GetNumberFormatA(lcid, dwFlags, SvPVX(number), &fmt, NULL, 0);
+    int len;
+    SV *number = newSVpvf("%.*f", NumDigits, V_R8(&variant));
+    char* pNumber = SvPVX(number);
+    WCHAR* wNumber = NULL;
+    if (USING_WIDE()) {
+	len = strlen(pNumber)+1;
+	New(0, wNumber, len, WCHAR);
+	A2WHELPER(pNumber, wNumber, len*sizeof(WCHAR));
+	len = GetNumberFormatW(lcid, dwFlags, wNumber, &wfmt, NULL, 0);
+    }
+    else {
+	len = GetNumberFormatA(lcid, dwFlags, pNumber, &afmt, NULL, 0);
+    }
     if (len > 1) {
-	SV *sv = ST(0) = sv_2mortal(newSV(len));
-	len = GetNumberFormatA(lcid, dwFlags, SvPVX(number), &fmt,
-			       SvPVX(sv), len);
-	if (len > 1) {
-	    SvCUR_set(sv, len-1);
-	    SvPOK_on(sv);
+	if (USING_WIDE()) {
+	    WCHAR* wInfo;
+	    char* pInfo;
+	    New(0, wInfo, len+1, WCHAR);
+	    New(0, pInfo, (len+1)*2, char);
+	    len = GetNumberFormatW(lcid, dwFlags, wNumber, &wfmt,
+				     wInfo, len);
+	    W2AHELPER(wInfo, pInfo, (len+1)*2);
+	    ST(0) = sv_2mortal(newSVpv(pInfo, 0));
+	    Safefree(pInfo);
+	    Safefree(wInfo);
+	}
+	else {
+	    SV *sv = ST(0) = sv_2mortal(newSV(len));
+	    len = GetNumberFormatA(lcid, dwFlags, pNumber, &afmt,
+				   SvPVX(sv), len);
+	    if (len > 1) {
+		SvCUR_set(sv, len-1);
+		SvPOK_on(sv);
+	    }
 	}
     }
     else
 	ST(0) = &PL_sv_undef;
 
+    if(wNumber)
+	Safefree(wNumber);
+
     SvREFCNT_dec(number);
     VariantClear(&variant);
     XSRETURN(1);
@@ -5474,7 +5692,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
@@ -5510,8 +5728,8 @@
 	XPUSHs(sv_2mortal(newRV_noinc((SV*)av)));
     }
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    if (CheckOleError(THIS_ olestash, hr))
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     /* return list of array refs on stack */
@@ -5525,11 +5743,11 @@
 PPCODE:
 {
     char *paszMethod[] = {"Get", "Put"};
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
     if (!pVarObj)
 	XSRETURN_EMPTY;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     VARIANT *pVariant = &pVarObj->variant;
 
     while (V_VT(pVariant) == (VT_VARIANT | VT_BYREF))
@@ -5545,16 +5763,16 @@
 	HRESULT hr;
 	if (ix == 0) { /* Get */
 	    ST(0) = sv_newmortal();
-	    hr = SetSVFromVariantEx(THIS_ pVariant, ST(0), olestash);
+	    hr = SetSVFromVariantEx(aTHX_ pVariant, ST(0), olestash);
 	}
 	else { /* Put */
-	    UINT cp = QueryPkgVar(THIS_ olestash, CP_NAME, CP_LEN, cpDefault);
-	    LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN,
+	    UINT cp = QueryPkgVar(aTHX_ olestash, CP_NAME, CP_LEN, cpDefault);
+	    LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN,
 				    lcidDefault);
 	    ST(0) = sv_mortalcopy(self);
-	    hr = AssignVariantFromSV(THIS_ ST(1), pVariant, cp, lcid);
+	    hr = AssignVariantFromSV(aTHX_ ST(1), pVariant, cp, lcid);
 	}
-	CheckOleError(THIS_ olestash, hr);
+	CheckOleError(aTHX_ olestash, hr);
 	XSRETURN(1);
     }
 
@@ -5571,12 +5789,12 @@
     if (ix == 1 && items == 2 && SvROK(ST(1)) &&
 	SvTYPE(SvRV(ST(1))) == SVt_PVAV)
     {
-	UINT cp = QueryPkgVar(THIS_ olestash, CP_NAME, CP_LEN, cpDefault);
-	LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN,
+	UINT cp = QueryPkgVar(aTHX_ olestash, CP_NAME, CP_LEN, cpDefault);
+	LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN,
 				lcidDefault);
-	HRESULT hr = SetSafeArrayFromAV(THIS_ (AV*)SvRV(ST(1)), vt_base, psa,
+	HRESULT hr = SetSafeArrayFromAV(aTHX_ (AV*)SvRV(ST(1)), vt_base, psa,
 					cDims, cp, lcid);
-	CheckOleError(THIS_ olestash, hr);
+	CheckOleError(aTHX_ olestash, hr);
 	ST(0) = sv_mortalcopy(self);
 	XSRETURN(1);
     }
@@ -5615,14 +5833,14 @@
 	hr = SafeArrayGetElement(psa, rgIndices, V_BYREF(&variant));
 	if (SUCCEEDED(hr)) {
 	    ST(0) = sv_newmortal();
-	    hr = SetSVFromVariantEx(THIS_ &variant, ST(0), olestash);
+	    hr = SetSVFromVariantEx(aTHX_ &variant, ST(0), olestash);
 	}
     }
     else { /* Put */
-	UINT cp = QueryPkgVar(THIS_ olestash, CP_NAME, CP_LEN, cpDefault);
-	LCID lcid = QueryPkgVar(THIS_ olestash, LCID_NAME, LCID_LEN,
+	UINT cp = QueryPkgVar(aTHX_ olestash, CP_NAME, CP_LEN, cpDefault);
+	LCID lcid = QueryPkgVar(aTHX_ olestash, LCID_NAME, LCID_LEN,
 				lcidDefault);
-	hr = AssignVariantFromSV(THIS_ ST(items-1), &variant, cp, lcid);
+	hr = AssignVariantFromSV(aTHX_ ST(items-1), &variant, cp, lcid);
 	if (SUCCEEDED(hr)) {
 	    if (vt_base == VT_BSTR)
 		hr = SafeArrayPutElement(psa, rgIndices, V_BSTR(&byref));
@@ -5638,7 +5856,7 @@
     }
     VariantClear(&byref);
     Safefree(rgIndices);
-    CheckOleError(THIS_ olestash, hr);
+    CheckOleError(aTHX_ olestash, hr);
     XSRETURN(1);
 }
 
@@ -5650,7 +5868,7 @@
     // Win32::OLE::Variant->LastError() exists only for backward compatibility.
     // It is now just a proxy for Win32::OLE->LastError().
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     SV *sv = items == 1 ? NULL : ST(1);
 
     PUSHMARK(sp);
@@ -5673,20 +5891,20 @@
     _RefType = 3
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
 
     ST(0) = &PL_sv_undef;
     if (pVarObj) {
 	HRESULT hr;
-	HV *olestash = GetWin32OleStash(THIS_ self);
-	SetLastOleError(THIS_ olestash);
+	HV *olestash = GetWin32OleStash(aTHX_ self);
+	SetLastOleError(aTHX_ olestash);
 	ST(0) = sv_newmortal();
 	if (ix == 0) /* Type */
 	    sv_setiv(ST(0), V_VT(&pVarObj->variant));
 	else if (ix == 1) /* Value */
-	    hr = SetSVFromVariantEx(THIS_ &pVarObj->variant, ST(0), olestash);
+	    hr = SetSVFromVariantEx(aTHX_ &pVarObj->variant, ST(0), olestash);
 	else if (ix == 2) /* _Value, see also: _Clone (alias of Copy) */
-	    hr = SetSVFromVariantEx(THIS_ &pVarObj->variant, ST(0), olestash,
+	    hr = SetSVFromVariantEx(aTHX_ &pVarObj->variant, ST(0), olestash,
 				    TRUE);
 	else if (ix == 3)  { /* _RefType */
 	    VARIANT *pVariant = &pVarObj->variant;
@@ -5694,7 +5912,7 @@
 		pVariant = V_VARIANTREF(pVariant);
 	    sv_setiv(ST(0), V_VT(pVariant));
 	}
-	CheckOleError(THIS_ olestash, hr);
+	CheckOleError(aTHX_ olestash, hr);
     }
     XSRETURN(1);
 }
@@ -5704,7 +5922,7 @@
     SV *self
 PPCODE:
 {
-    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(THIS_ self);
+    WINOLEVARIANTOBJECT *pVarObj = GetOleVariantObject(aTHX_ self);
 
     ST(0) = &PL_sv_undef;
     if (pVarObj) {
@@ -5712,18 +5930,18 @@
 	VARIANT *pVariant = &pVarObj->variant;
 	HRESULT hr = S_OK;
 
-	HV *olestash = GetWin32OleStash(THIS_ self);
-	SetLastOleError(THIS_ olestash);
+	HV *olestash = GetWin32OleStash(aTHX_ self);
+	SetLastOleError(aTHX_ olestash);
 	VariantInit(&Variant);
 	if ((V_VT(pVariant) & ~VT_BYREF) != VT_BSTR) {
-	    LCID lcid = QueryPkgVar(THIS_ olestash,
+	    LCID lcid = QueryPkgVar(aTHX_ olestash,
 				    LCID_NAME, LCID_LEN, lcidDefault);
 
 	    hr = VariantChangeTypeEx(&Variant, pVariant, lcid, 0, VT_BSTR);
 	    pVariant = &Variant;
 	}
 
-	if (!CheckOleError(THIS_ olestash, hr)) {
+	if (!CheckOleError(aTHX_ olestash, hr)) {
 	    BSTR bstr = V_ISBYREF(pVariant) ? *V_BSTRREF(pVariant)
 		                            : V_BSTR(pVariant);
 	    STRLEN olecharlen = SysStringLen(bstr);
@@ -5756,8 +5974,19 @@
     STRLEN length2;
     char *string1 = SvPV(str1, length1);
     char *string2 = SvPV(str2, length2);
+    int res;
 
-    int res = CompareStringA(lcid, flags, string1, length1, string2, length2);
+    if (USING_WIDE()) {
+	WCHAR *wstring1, *wstring2;
+	New(0, wstring1, length1+1, WCHAR);
+	New(0, wstring2, length2+1, WCHAR);
+	A2WHELPER(string1, wstring1, (length1+1)*sizeof(WCHAR));
+	A2WHELPER(string2, wstring2, (length2+1)*sizeof(WCHAR));
+	res = CompareStringW(lcid, flags, wstring1, -1, wstring2, -1);
+    }
+    else {
+	res = CompareStringA(lcid, flags, string1, length1, string2, length2);
+    }
     XSRETURN_IV(res);
 }
 
@@ -5768,18 +5997,48 @@
     SV *str
 PPCODE:
 {
-    SV *sv = sv_newmortal();
+    SV *sv;
+    int len;
     STRLEN length;
+    WCHAR* wstring = NULL;
     char *string = SvPV(str,length);
-    int len = LCMapStringA(lcid, flags, string, length, NULL, 0);
+    if (USING_WIDE()) {
+	len = strlen(string)+1;
+	New(0, wstring, len, WCHAR);
+	A2WHELPER(string, wstring, len*sizeof(WCHAR));
+	len = LCMapStringW(lcid, flags, wstring, -1, NULL, 0);
+    }
+    else {
+	len = LCMapStringA(lcid, flags, string, length, NULL, 0);
+    }
     if (len > 0) {
-	SvUPGRADE(sv, SVt_PV);
-	SvGROW(sv, len+1);
-	SvCUR_set(sv, LCMapStringA(lcid, flags, string, length,
-				   SvPVX(sv), SvLEN(sv)));
-	if (SvCUR(sv))
-	    SvPOK_on(sv);
+	if (USING_WIDE()) {
+	    WCHAR* wInfo;
+	    char* pInfo;
+	    New(0, wInfo, len+1, WCHAR);
+	    New(0, pInfo, (len+1)*2, char);
+	    len = LCMapStringW(lcid, flags, wstring, -1, wInfo, len);
+	    W2AHELPER(wInfo, pInfo, (len+1)*2);
+	    sv = sv_2mortal(newSVpv(pInfo, 0));
+	    Safefree(pInfo);
+	    Safefree(wInfo);
+	}
+	else {
+	    sv = sv_newmortal();
+	    SvUPGRADE(sv, SVt_PV);
+	    SvGROW(sv, len+1);
+	    SvCUR_set(sv, LCMapStringA(lcid, flags, string, length,
+				       SvPVX(sv), SvLEN(sv)));
+	    if (SvCUR(sv))
+		SvPOK_on(sv);
+	}
     }
+    else
+	sv = sv_newmortal();
+
+    if(wstring)
+	Safefree(wstring);
+
     ST(0) = sv;
     XSRETURN(1);
 }
@@ -5790,15 +6049,30 @@
     IV lctype
 PPCODE:
 {
-    SV *sv = sv_newmortal();
-    int len = GetLocaleInfoA(lcid, lctype, NULL, 0);
-    if (len > 0) {
-	SvUPGRADE(sv, SVt_PV);
-	SvGROW(sv, len);
-	len = GetLocaleInfoA(lcid, lctype, SvPVX(sv), SvLEN(sv));
-	if (len) {
-	    SvCUR_set(sv, len-1);
-	    SvPOK_on(sv);
+    SV *sv;
+    if (USING_WIDE()) {
+	WCHAR *info;
+	char *szInfo;
+	int len = GetLocaleInfoW(lcid, lctype, NULL, 0);
+	New(0, info, len, WCHAR);
+	GetLocaleInfoW(lcid, lctype, info, len);
+	New(0, szInfo, len*2, char);
+	W2AHELPER(info, szInfo, len*2);
+	sv = sv_2mortal(newSVpv(szInfo, 0));
+	Safefree(info);
+	Safefree(szInfo);
+    }
+    else {
+	sv = sv_newmortal();
+	int len = GetLocaleInfoA(lcid, lctype, NULL, 0);
+	if (len > 0) {
+	    SvUPGRADE(sv, SVt_PV);
+	    SvGROW(sv, len);
+	    len = GetLocaleInfoA(lcid, lctype, SvPVX(sv), SvLEN(sv));
+	    if (len) {
+		SvCUR_set(sv, len-1);
+		SvPOK_on(sv);
+	    }
 	}
     }
     ST(0) = sv;
@@ -5887,7 +6161,19 @@
     char *lcdata
 PPCODE:
 {
-    if (SetLocaleInfoA(lcid, lctype, lcdata))
+    BOOL result;
+    if (USING_WIDE()) {
+	WCHAR* wlcdata;
+	int len = strlen(lcdata)+1;
+	New(0, wlcdata, len, WCHAR);
+	A2WHELPER(lcdata, wlcdata, len*sizeof(WCHAR));
+	result = SetLocaleInfoW(lcid, lctype, wlcdata);
+	Safefree(wlcdata);
+    }
+    else {
+	result = SetLocaleInfoA(lcid, lctype, lcdata);
+    }
+    if(result)
 	XSRETURN_YES;
 
     XSRETURN_EMPTY;
@@ -5910,48 +6196,48 @@
     TLIBATTR *pTLibAttr;
 
     if (sv_isobject(object) && sv_derived_from(object, szWINOLE)) {
-	WINOLEOBJECT *pOleObj = GetOleObject(THIS_ object);
+	WINOLEOBJECT *pOleObj = GetOleObject(aTHX_ object);
 	if (!pOleObj)
 	    XSRETURN_EMPTY;
 
 	unsigned int count;
 	hr = pOleObj->pDispatch->GetTypeInfoCount(&count);
 	stash = SvSTASH(pOleObj->self);
-	if (CheckOleError(THIS_ stash, hr) || count == 0)
+	if (CheckOleError(aTHX_ stash, hr) || count == 0)
 	    XSRETURN_EMPTY;
 
 	ITypeInfo *pTypeInfo;
 	hr = pOleObj->pDispatch->GetTypeInfo(0, lcidDefault, &pTypeInfo);
-	if (CheckOleError(THIS_ stash, hr))
+	if (CheckOleError(aTHX_ stash, hr))
 	    XSRETURN_EMPTY;
 
 	unsigned int index;
 	hr = pTypeInfo->GetContainingTypeLib(&pTypeLib, &index);
 	pTypeInfo->Release();
-	if (CheckOleError(THIS_ stash, hr))
+	if (CheckOleError(aTHX_ stash, hr))
 	    XSRETURN_EMPTY;
     }
     else {
-	stash = GetWin32OleStash(THIS_ self);
-	UINT cp = QueryPkgVar(THIS_ stash, CP_NAME, CP_LEN, cpDefault);
+	stash = GetWin32OleStash(aTHX_ self);
+	UINT cp = QueryPkgVar(aTHX_ stash, CP_NAME, CP_LEN, cpDefault);
 
 	char *pszBuffer = SvPV_nolen(object);
 	OLECHAR Buffer[OLE_BUF_SIZ];
-	OLECHAR *pBuffer = GetWideChar(THIS_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
+	OLECHAR *pBuffer = GetWideChar(aTHX_ pszBuffer, Buffer, OLE_BUF_SIZ, cp);
 	hr = LoadTypeLibEx(pBuffer, REGKIND_NONE, &pTypeLib);
-	ReleaseBuffer(THIS_ pBuffer, Buffer);
-	if (CheckOleError(THIS_ stash, hr))
+	ReleaseBuffer(aTHX_ pBuffer, Buffer);
+	if (CheckOleError(aTHX_ stash, hr))
 	    XSRETURN_EMPTY;
     }
 
     hr = pTypeLib->GetLibAttr(&pTLibAttr);
     if (FAILED(hr)) {
 	pTypeLib->Release();
-	ReportOleError(THIS_ stash, hr);
+	ReportOleError(aTHX_ stash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeLibObject(THIS_ pTypeLib, pTLibAttr));
+    ST(0) = sv_2mortal(CreateTypeLibObject(aTHX_ pTypeLib, pTLibAttr));
     XSRETURN(1);
 }
 
@@ -5960,9 +6246,9 @@
     SV *self
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (pObj) {
-	RemoveFromObjectChain(THIS_ (OBJECTHEADER*)pObj);
+	RemoveFromObjectChain(aTHX_ (OBJECTHEADER*)pObj);
 	if (pObj->pTypeLib) {
 	    pObj->pTypeLib->ReleaseTLibAttr(pObj->pTLibAttr);
 	    pObj->pTypeLib->Release();
@@ -5978,7 +6264,7 @@
     IV index
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -5986,11 +6272,11 @@
     BSTR bstrName, bstrDocString, bstrHelpFile;
     HRESULT hr = pObj->pTypeLib->GetDocumentation(index, &bstrName,
 			  &bstrDocString, &dwHelpContext, &bstrHelpFile);
-    HV *olestash = GetWin32OleStash(THIS_ self);
-    if (CheckOleError(THIS_ olestash, hr))
+    HV *olestash = GetWin32OleStash(aTHX_ self);
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
-    HV *hv = GetDocumentation(THIS_ bstrName, bstrDocString,
+    HV *hv = GetDocumentation(aTHX_ bstrName, bstrDocString,
 			      dwHelpContext, bstrHelpFile);
     ST(0) = sv_2mortal(newRV_noinc((SV*)hv));
     XSRETURN(1);
@@ -6001,7 +6287,7 @@
     SV *self
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -6013,7 +6299,7 @@
     hv_store(hv, "wLibFlags",     9, newSViv(p->wLibFlags), 0);
     hv_store(hv, "wMajorVerNum", 12, newSViv(p->wMajorVerNum), 0);
     hv_store(hv, "wMinorVerNum", 12, newSViv(p->wMinorVerNum), 0);
-    hv_store(hv, "guid",          4, SetSVFromGUID(THIS_ p->guid), 0);
+    hv_store(hv, "guid",          4, SetSVFromGUID(aTHX_ p->guid), 0);
 
     ST(0) = sv_2mortal(newRV_noinc((SV*)hv));
     XSRETURN(1);
@@ -6024,7 +6310,7 @@
     SV *self
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
@@ -6037,26 +6323,26 @@
     IV index
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     ITypeInfo *pTypeInfo;
     TYPEATTR  *pTypeAttr;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeLib->GetTypeInfo(index, &pTypeInfo);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ olestash, hr);
+	ReportOleError(aTHX_ olestash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr));
+    ST(0) = sv_2mortal(CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr));
     XSRETURN(1);
 }
 
@@ -6066,46 +6352,46 @@
     SV *name
 PPCODE:
 {
-    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(THIS_ self);
+    WINOLETYPELIBOBJECT *pObj = GetOleTypeLibObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     ITypeInfo *pTypeInfo;
     TYPEATTR  *pTypeAttr;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
 
     if (SvIOK(name)) {
 	HRESULT hr = pObj->pTypeLib->GetTypeInfo(SvIV(name), &pTypeInfo);
-	if (CheckOleError(THIS_ olestash, hr))
+	if (CheckOleError(aTHX_ olestash, hr))
 	    XSRETURN_EMPTY;
 
 	hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
 	if (FAILED(hr)) {
 	    pTypeInfo->Release();
-	    ReportOleError(THIS_ olestash, hr);
+	    ReportOleError(aTHX_ olestash, hr);
 	    XSRETURN_EMPTY;
 	}
 
-	ST(0) = sv_2mortal(CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr));
+	ST(0) = sv_2mortal(CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr));
 	XSRETURN(1);
     }
 
-    UINT cp = QueryPkgVar(THIS_ olestash, CP_NAME, CP_LEN, cpDefault);
+    UINT cp = QueryPkgVar(aTHX_ olestash, CP_NAME, CP_LEN, cpDefault);
     TYPEKIND tkind = items > 2 ? (TYPEKIND)SvIV(ST(2)) : TKIND_MAX;
     char *pszName = SvPV_nolen(name);
     int count = pObj->pTypeLib->GetTypeInfoCount();
     for (int index = 0; index < count; ++index) {
 	HRESULT hr = pObj->pTypeLib->GetTypeInfo(index, &pTypeInfo);
-	if (CheckOleError(THIS_ olestash, hr))
+	if (CheckOleError(aTHX_ olestash, hr))
 	    XSRETURN_EMPTY;
 
 	BSTR bstrName;
 	hr = pTypeInfo->GetDocumentation(-1, &bstrName, NULL, NULL, NULL);
 	char szStr[OLE_BUF_SIZ];
-	char *pszStr = GetMultiByte(THIS_ bstrName, szStr, sizeof(szStr), cp);
+	char *pszStr = GetMultiByte(aTHX_ bstrName, szStr, sizeof(szStr), cp);
 	int equal = strEQ(pszStr, pszName);
-	ReleaseBuffer(THIS_ pszStr, szStr);
+	ReleaseBuffer(aTHX_ pszStr, szStr);
 	SysFreeString(bstrName);
 	if (!equal) {
 	    pTypeInfo->Release();
@@ -6115,12 +6401,12 @@
 	hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
 	if (FAILED(hr)) {
 	    pTypeInfo->Release();
-	    ReportOleError(THIS_ olestash, hr);
+	    ReportOleError(aTHX_ olestash, hr);
 	    XSRETURN_EMPTY;
 	}
 
 	if (tkind == TKIND_MAX || tkind == pTypeAttr->typekind) {
-	    ST(0) = sv_2mortal(CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr));
+	    ST(0) = sv_2mortal(CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr));
 	    XSRETURN(1);
 	}
 
@@ -6143,28 +6429,28 @@
     ITypeInfo *pTypeInfo;
     TYPEATTR  *pTypeAttr;
 
-    WINOLEOBJECT *pOleObj = GetOleObject(THIS_ object);
+    WINOLEOBJECT *pOleObj = GetOleObject(aTHX_ object);
     if (!pOleObj)
         XSRETURN_EMPTY;
 
     unsigned int count;
     HRESULT hr = pOleObj->pDispatch->GetTypeInfoCount(&count);
     HV *olestash = SvSTASH(pOleObj->self);
-    if (CheckOleError(THIS_ olestash, hr) || count == 0)
+    if (CheckOleError(aTHX_ olestash, hr) || count == 0)
         XSRETURN_EMPTY;
 
     hr = pOleObj->pDispatch->GetTypeInfo(0, lcidDefault, &pTypeInfo);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
         XSRETURN_EMPTY;
 
     hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ olestash, hr);
+	ReportOleError(aTHX_ olestash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeInfoObject(THIS_ pTypeInfo, pTypeAttr));
+    ST(0) = sv_2mortal(CreateTypeInfoObject(aTHX_ pTypeInfo, pTypeAttr));
     XSRETURN(1);
 }
 
@@ -6173,9 +6459,9 @@
     SV *self
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (pObj) {
-	RemoveFromObjectChain(THIS_ (OBJECTHEADER*)pObj);
+	RemoveFromObjectChain(aTHX_ (OBJECTHEADER*)pObj);
 	if (pObj->pTypeInfo) {
 	    pObj->pTypeInfo->ReleaseTypeAttr(pObj->pTypeAttr);
 	    pObj->pTypeInfo->Release();
@@ -6193,24 +6479,24 @@
     ITypeLib  *pTypeLib;
     TLIBATTR  *pTLibAttr;
 
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     unsigned int index;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetContainingTypeLib(&pTypeLib, &index);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
         XSRETURN_EMPTY;
 
     hr = pTypeLib->GetLibAttr(&pTLibAttr);
     if (FAILED(hr)) {
 	pTypeLib->Release();
-	ReportOleError(THIS_ olestash, hr);
+	ReportOleError(aTHX_ olestash, hr);
 	XSRETURN_EMPTY;
     }
 
-    ST(0) = sv_2mortal(CreateTypeLibObject(THIS_ pTypeLib, pTLibAttr));
+    ST(0) = sv_2mortal(CreateTypeLibObject(aTHX_ pTypeLib, pTLibAttr));
     XSRETURN(1);
 }
 
@@ -6220,19 +6506,19 @@
     IV memid
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     DWORD dwHelpContext;
     BSTR bstrName, bstrDocString, bstrHelpFile;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetDocumentation(memid, &bstrName,
 			   &bstrDocString, &dwHelpContext, &bstrHelpFile);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
-    HV *hv = GetDocumentation(THIS_ bstrName, bstrDocString,
+    HV *hv = GetDocumentation(aTHX_ bstrName, bstrDocString,
 			      dwHelpContext, bstrHelpFile);
     ST(0) = sv_2mortal(newRV_noinc((SV*)hv));
     XSRETURN(1);
@@ -6244,14 +6530,14 @@
     IV index
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     FUNCDESC *p;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetFuncDesc(index, &p);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     HV *hv = newHV();
@@ -6266,14 +6552,14 @@
     hv_store(hv, "cScodes",       7, newSViv(p->cScodes), 0);
     hv_store(hv, "wFuncFlags",   10, newSViv(p->wFuncFlags), 0);
 
-    HV *elemdesc = TranslateElemDesc(THIS_ &p->elemdescFunc, pObj, olestash);
+    HV *elemdesc = TranslateElemDesc(aTHX_ &p->elemdescFunc, pObj, olestash);
     hv_store(hv, "elemdescFunc", 12, newRV_noinc((SV*)elemdesc), 0);
 
     if (p->cParams > 0) {
 	AV *av = newAV();
 
 	for (int i = 0; i < p->cParams; ++i) {
-	    elemdesc = TranslateElemDesc(THIS_ &p->lprgelemdescParam[i],
+	    elemdesc = TranslateElemDesc(aTHX_ &p->lprgelemdescParam[i],
 					 pObj, olestash);
 	    av_push(av, newRV_noinc((SV*)elemdesc));
 	}
@@ -6291,14 +6577,14 @@
     IV index
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     int flags;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetImplTypeFlags(index, &flags);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     XSRETURN_IV(flags);
@@ -6314,23 +6600,23 @@
     ITypeInfo *pTypeInfo;
     TYPEATTR  *pTypeAttr;
 
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetRefTypeOfImplType(index, &hRefType);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     hr = pObj->pTypeInfo->GetRefTypeInfo(hRefType, &pTypeInfo);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
     if (FAILED(hr)) {
 	pTypeInfo->Release();
-	ReportOleError(THIS_ olestash, hr);
+	ReportOleError(aTHX_ olestash, hr);
 	XSRETURN_EMPTY;
     }
 
@@ -6338,10 +6624,10 @@
     pObj->pTypeInfo = pTypeInfo;
     pObj->pTypeAttr = pTypeAttr;
 
-    AddToObjectChain(THIS_ (OBJECTHEADER*)pObj, WINOLETYPEINFO_MAGIC);
+    AddToObjectChain(aTHX_ (OBJECTHEADER*)pObj, WINOLETYPEINFO_MAGIC);
 
     SV *sv = newSViv((IV)pObj);
-    ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), GetStash(THIS_ self)));
+    ST(0) = sv_2mortal(sv_bless(newRV_noinc(sv), GetStash(aTHX_ self)));
     XSRETURN(1);
 }
 
@@ -6352,27 +6638,27 @@
     IV count
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     BSTR *rgbstr;
     New(0, rgbstr, count, BSTR);
     unsigned int cNames;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetNames(memid, rgbstr, count, &cNames);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     AV *av = newAV();
     for (int i = 0; i < cNames; ++i) {
 	char szName[32];
 	// XXX use correct codepage ???
-	char *pszName = GetMultiByte(THIS_ rgbstr[i],
+	char *pszName = GetMultiByte(aTHX_ rgbstr[i],
 				     szName, sizeof(szName), CP_ACP);
 	SysFreeString(rgbstr[i]);
 	av_push(av, newSVpv(pszName, 0));
-	ReleaseBuffer(THIS_ pszName, szName);
+	ReleaseBuffer(aTHX_ pszName, szName);
     }
     Safefree(rgbstr);
 
@@ -6385,14 +6671,14 @@
     SV *self
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     TYPEATTR *p = pObj->pTypeAttr;
     HV *hv = newHV();
 
-    hv_store(hv, "guid",              4, SetSVFromGUID(THIS_ p->guid), 0);
+    hv_store(hv, "guid",              4, SetSVFromGUID(aTHX_ p->guid), 0);
     hv_store(hv, "lcid",              4, newSViv(p->lcid), 0);
     hv_store(hv, "memidConstructor", 16, newSViv(p->memidConstructor), 0);
     hv_store(hv, "memidDestructor",  15, newSViv(p->memidDestructor), 0);
@@ -6421,14 +6707,14 @@
     IV index
 PPCODE:
 {
-    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(THIS_ self);
+    WINOLETYPEINFOOBJECT *pObj = GetOleTypeInfoObject(aTHX_ self);
     if (!pObj)
 	XSRETURN_EMPTY;
 
     VARDESC *p;
-    HV *olestash = GetWin32OleStash(THIS_ self);
+    HV *olestash = GetWin32OleStash(aTHX_ self);
     HRESULT hr = pObj->pTypeInfo->GetVarDesc(index, &p);
-    if (CheckOleError(THIS_ olestash, hr))
+    if (CheckOleError(aTHX_ olestash, hr))
 	XSRETURN_EMPTY;
 
     HV *hv = newHV();
@@ -6437,7 +6723,7 @@
     hv_store(hv, "wVarFlags",    9, newSViv(p->wVarFlags), 0);
     hv_store(hv, "varkind",      7, newSViv(p->varkind), 0);
 
-    HV *elemdesc = TranslateElemDesc(THIS_ &p->elemdescVar,
+    HV *elemdesc = TranslateElemDesc(aTHX_ &p->elemdescVar,
 				     pObj, olestash);
     hv_store(hv, "elemdescVar", 11, newRV_noinc((SV*)elemdesc), 0);
 
@@ -6447,7 +6733,7 @@
     if (p->varkind == VAR_CONST) {
 	// XXX should be stored as a Win32::OLE::Variant object ?
 	SV *sv = newSV(0);
-	SetSVFromVariantEx(THIS_ p->lpvarValue, sv, olestash);
+	SetSVFromVariantEx(aTHX_ p->lpvarValue, sv, olestash);
 	hv_store(hv, "varValue", 8, sv, 0);
     }
 
diff -ur libwin32-0.16/OLE/lib/Win32/OLE.pm libwin32-0.171/OLE/lib/Win32/OLE.pm
--- libwin32-0.16/OLE/lib/Win32/OLE.pm	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/OLE/lib/Win32/OLE.pm	Tue Sep 19 16:39:23 2000
@@ -6,7 +6,7 @@
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK @EXPORT_FAIL $AUTOLOAD
 	    $CP $LCID $Warn $LastError $_NewEnum $_Unique);
 
-$VERSION = '0.13';
+$VERSION = '0.1401';
 
 use Carp;
 use Exporter;
@@ -949,6 +949,6 @@
 
 =head1 VERSION
 
-Version 0.13	  9 May 2000
+Version 0.1401	  11 September 2000
 
 =cut
diff -ur libwin32-0.16/OLE/t/3_ole.t libwin32-0.171/OLE/t/3_ole.t
--- libwin32-0.16/OLE/t/3_ole.t	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/OLE/t/3_ole.t	Tue Sep 19 16:39:24 2000
@@ -218,18 +218,24 @@
 print "not " unless $ValOf == 25 && $RefOf->Value == 27;
 printf "ok %d\n", ++$Test;
 
-# 16. Test 'SetProperty' function
+# 16. Assign and retrieve a very long string
+$Cell->{Value} = 'a' x 300;
+printf "# Value is %s\n", $Cell->Value;
+print "not " unless $Cell->Value eq ('a' x 300);
+printf "ok %d\n", ++$Test;
+
+# 17. Test 'SetProperty' function
 $Cell->SetProperty('Value', 4711);
 printf "# Value is %s\n", $Cell->Value;
 print "not " unless $Cell->Value == 4711;
 printf "ok %d\n", ++$Test;
 
-# 17. The following tests rely on the fact that the font is not yet bold
+# 18. The following tests rely on the fact that the font is not yet bold
 printf "# Bold: %s\n", $Cell->Style->Font->Bold;
 print "not " if $Cell->Style->Font->Bold;
 printf "ok %d\n", ++$Test;
 
-# 18. Assignment by DISPATCH_PROPERTYPUTREF shouldn't work
+# 19. Assignment by DISPATCH_PROPERTYPUTREF shouldn't work
 my $Style = $Book->Styles->Add("MyStyle");
 $Style->Font->{Bold} = 1;
 { local $Excel::Warn = 0; $Cell->{Style} = $Style }
@@ -239,63 +245,63 @@
 print "not " if $LastError != HRESULT(0x80020003) || $Cell->Style->Font->Bold;
 printf "ok %d\n", ++$Test;
 
-# 19. But DISPATCH_PROPERTYPUT should be ok
+# 20. But DISPATCH_PROPERTYPUT should be ok
 $Cell->LetProperty('Style', $Style);
 printf "# Bold: %s\n", $Cell->Style->Font->Bold;
 print "not " unless $Cell->Style->Font->Bold;
 printf "ok %d\n", ++$Test;
 
-# 20. Set a cell range from an array ref containing an IV, PV and NV
+# 21. Set a cell range from an array ref containing an IV, PV and NV
 $Sheet->Range("A8:C9")->{Value} = [[undef, 'Camel'],[42, 'Perl', 3.1415]];
 $Value = $Sheet->Cells(9,2)->Value . $Sheet->Cells(8,2)->Value;
 print "# Value is \"$Value\"\n";
 print "not " unless $Value eq 'PerlCamel';
 printf "ok %d\n", ++$Test;
 
-# 21. Retrieve float value (esp. interesting in foreign locales)
+# 22. Retrieve float value (esp. interesting in foreign locales)
 $Value = $Sheet->Cells(9,3)->{Value};
 print "# Value is \"$Value\"\n";
 print "not " unless $Value == 3.1415;
 printf "ok %d\n", ++$Test;
 
-# 22. Retrieve a 0 dimensional range; check array data structure
+# 23. Retrieve a 0 dimensional range; check array data structure
 $Value = $Sheet->Range("B8")->{Value};
 printf "# Values are: \"%s\"\n", stringify($Value);
 print "not " if ref $Value;
 printf "ok %d\n", ++$Test;
 
-# 23. Retrieve a 1 dimensional row range; check array data structure
+# 24. Retrieve a 1 dimensional row range; check array data structure
 $Value = $Sheet->Range("B8:C8")->{Value};
 printf "# Values are: \"%s\"\n", stringify($Value);
 print "not " unless @$Value == 1 && ref $$Value[0];
 printf "ok %d\n", ++$Test;
 
-# 24. Retrieve a 1 dimensional column range; check array data structure
+# 25. Retrieve a 1 dimensional column range; check array data structure
 $Value = $Sheet->Range("B8:B9")->{Value};
 printf "# Values are: \"%s\"\n", stringify($Value);
 print "not " unless @$Value == 2 && ref $$Value[0] && ref $$Value[1];
 printf "ok %d\n", ++$Test;
 
-# 25. Retrieve a 2 dimensional range; check array data structure
+# 26. Retrieve a 2 dimensional range; check array data structure
 $Value = $Sheet->Range("B8:C9")->{Value};
 printf "# Values are: \"%s\"\n", stringify($Value);
 print "not " unless @$Value == 2 && ref $$Value[0] && ref $$Value[1];
 printf "ok %d\n", ++$Test;
 
-# 26. Check contents of 2 dimensional array
+# 27. Check contents of 2 dimensional array
 $Value = $$Value[0][0] . $$Value[1][0] . $$Value[1][1];
 print "# Value is \"$Value\"\n";
 print "not " unless $Value eq 'CamelPerl3.1415';
 printf "ok %d\n", ++$Test;
 
-# 27. Set a cell formula and retrieve calculated value
+# 28. Set a cell formula and retrieve calculated value
 $Sheet->Cells(3,1)->{Formula} = '=PI()';
 $Value = $Sheet->Cells(3,1)->{Value};
 print "# Value is \"$Value\"\n";
 print "not " unless abs($Value-3.141592) < 0.00001;
 printf "ok %d\n", ++$Test;
 
-# 28. Add single worksheet and check that worksheet count is incremented
+# 29. Add single worksheet and check that worksheet count is incremented
 my $Count = $Sheets->{Count};
 $Book->Worksheets->Add;
 $Value = $Sheets->{Count};
@@ -303,7 +309,7 @@
 print "not " unless $Value == $Count+1;
 printf "ok %d\n", ++$Test;
 
-# 29. Add 2 more sheets, optional arguments are omitted
+# 30. Add 2 more sheets, optional arguments are omitted
 $Count = $Sheets->{Count};
 $Book->Worksheets->Add(undef,undef,2);
 $Value = $Sheets->{Count};
@@ -311,7 +317,7 @@
 print "not " unless $Value == $Count+2;
 printf "ok %d\n", ++$Test;
 
-# 30. Add 3 more sheets before sheet 2 using a named argument
+# 31. Add 3 more sheets before sheet 2 using a named argument
 $Count = $Sheets->{Count};
 $Book->Worksheets(2)->{Name} = 'XYZZY';
 $Sheets->Add($Book->Worksheets(2), {Count => 3});
@@ -320,13 +326,13 @@
 print "not " unless $Value == $Count+3;
 printf "ok %d\n", ++$Test;
 
-# 31. Previous sheet 2 should now be sheet 5
+# 32. Previous sheet 2 should now be sheet 5
 $Value = $Book->Worksheets(5)->{Name};
 print "# Value is \"$Value\"\n";
 print "not " unless $Value eq 'XYZZY';
 printf "ok %d\n", ++$Test;
 
-# 32. Add 2 more sheets at the end using 2 named arguments
+# 33. Add 2 more sheets at the end using 2 named arguments
 $Count = $Sheets->{Count};
 # Following line doesn't work with Excel 7 (Seems like an Excel bug?)
 # $Sheets->Add({Count => 2, After => $Book->Worksheets($Sheets->{Count})});
@@ -334,7 +340,7 @@
 print "not " unless $Sheets->{Count} == $Count+2;
 printf "ok %d\n", ++$Test;
 
-# 33. Number of objects in an enumeration must match its "Count" property
+# 34. Number of objects in an enumeration must match its "Count" property
 my @Sheets = in $Sheets;
 printf "# \$Sheets->{Count} is %d\n", $Sheets->{Count};
 printf "# scalar(\@Sheets) is %d\n", scalar(@Sheets);
@@ -345,7 +351,7 @@
 printf "ok %d\n", ++$Test;
 undef @Sheets;
 
-# 34. Enumerate all application properties using the C<keys> function
+# 35. Enumerate all application properties using the C<keys> function
 my @Properties = keys %$Excel;
 printf "# Number of Excel application properties: %d\n", scalar(@Properties);
 $Value = grep /^(Parent|Xyzzy|Name)$/, @Properties;
@@ -354,7 +360,7 @@
 printf "ok %d\n", ++$Test;
 undef @Properties;
 
-# 35. Translate character from ANSI -> OEM
+# 36. Translate character from ANSI -> OEM
 my ($Version) = $Excel->{Version} =~ /([0-9.]+)/;
 print "# Excel version is $Version\n";
 
@@ -373,15 +379,15 @@
 print "not " unless ord($ANSI) == 163 && ord($OEM) == 156;
 printf "ok %d\n", ++$Test;
 
-# 36. Save workbook to file
+# 37. Save workbook to file
 print "not " unless $Book->SaveAs($File);
 printf "ok %d\n", ++$Test;
 
-# 37. Check if output file exists.
+# 38. Check if output file exists.
 print "not " unless -f $File;
 printf "ok %d\n", ++$Test;
 
-# 38. Access the same file object through a moniker.
+# 39. Access the same file object through a moniker.
 $Obj = Win32::OLE->GetObject($File);
 for ($Count=0 ; $Count < 5 ; ++$Count) {
     my $Type = Win32::OLE->QueryObjectType($Obj);
@@ -396,7 +402,7 @@
 printf "ok %d\n", ++$Test;
 
 
-# 39. Get return value as Win32::OLE::Variant object
+# 40. Get return value as Win32::OLE::Variant object
 $Cell = $Obj->Worksheets('My Sheet #1')->Range('B9');
 my $Variant = Win32::OLE::Variant->new(VT_EMPTY);
 $Cell->Dispatch('Value', $Variant);
@@ -404,7 +410,7 @@
 print "not " unless $Variant->Type == VT_BSTR && $Variant->Value eq 'Perl';
 printf "ok %d\n", ++$Test;
 
-# 40. Use clsid string to start OLE server
+# 41. Use clsid string to start OLE server
 undef $Value;
 eval {
     require Win32::Registry;
@@ -428,7 +434,7 @@
     printf "ok %d\n", $Test;
 }
 
-# 41. Use DCOM syntax to start server (on local machine though)
+# 42. Use DCOM syntax to start server (on local machine though)
 #     This might fail (on Win95/NT3.5 if DCOM support is not installed.
 $Obj = Win32::OLE->new([hostname, 'Excel.Application'], 'Quit');
 $Value = (Win32::OLE->QueryObjectType($Obj))[0];
@@ -436,7 +442,7 @@
 print "not " unless $Value eq 'Excel';
 printf "ok %d\n", ++$Test;
 
-# 42. Find $Excel object via EnumAllObjects()
+# 43. Find $Excel object via EnumAllObjects()
 my $Found = 0;
 $Count = Win32::OLE->EnumAllObjects(sub {
     my $Object = shift;
@@ -448,38 +454,38 @@
 print "not " unless $Found;
 printf "ok %d\n", ++$Test;
 
-# 43. _NewEnum should normally be non-browseable
+# 44. _NewEnum should normally be non-browseable
 my $Exists = grep /^_NewEnum$/, keys %{$Excel->Worksheets};
 print "# Exists=$Exists\n";
 print "not " if $Exists;
 printf "ok %d\n", ++$Test;
 
-# 44. make _NewEnum visible
+# 45. make _NewEnum visible
 Excel->Option(_NewEnum => 1);
 $Exists = grep /^_NewEnum$/, keys %{$Excel->Worksheets};
 print "# Exists=$Exists\n";
 print "not " unless $Exists;
 printf "ok %d\n", ++$Test;
 
-# 45. _NewEnum available as a method
+# 46. _NewEnum available as a method
 @Sheets = @{$Excel->Worksheets->_NewEnum};
 print "# $_->{Name}\n" foreach @Sheets;
 print "not " unless @Sheets == 11 && grep $_->Name eq "My Sheet #1", @Sheets;
 printf "ok %d\n", ++$Test;
 
-# 46. _NewEnum available as a property
+# 47. _NewEnum available as a property
 @Sheets = @{$Excel->Worksheets->{_NewEnum}};
 print "not " unless @Sheets == 11 && grep $_->Name eq "My Sheet #1", @Sheets;
 printf "ok %d\n", ++$Test;
 
-# 47. Win32::OLE proxies are non-unique by default
+# 48. Win32::OLE proxies are non-unique by default
 my $Application = $Excel->Application;
 my $Parent = $Excel->Parent;
 printf "# Application=%d Parent=%d\n", $Application, $Parent;
 print "not " if $Application == $Parent;
 printf "ok %d\n", ++$Test;
 
-# 48. Parent and Application property should now return the same object
+# 49. Parent and Application property should now return the same object
 Excel->Option(_Unique => 1);
 $Application = $Excel->Application;
 $Parent = $Excel->Parent;
@@ -487,5 +493,5 @@
 print "not " unless $Application == $Parent;
 printf "ok %d\n", ++$Test;
 
-# 49. Terminate server instance ("ok $Test\n" printed by Excel destructor)
+# 50. Terminate server instance ("ok $Test\n" printed by Excel destructor)
 exit;
diff -ur libwin32-0.16/PerfLib/PerfLib.xs libwin32-0.171/PerfLib/PerfLib.xs
--- libwin32-0.16/PerfLib/PerfLib.xs	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/PerfLib/PerfLib.xs	Tue Sep 19 16:39:24 2000
@@ -965,7 +965,7 @@
 	    RETVAL = RegQueryInfoKeyA(remote_perfkey, NULL, NULL, NULL, NULL,
 				 NULL, NULL, NULL, NULL, &value_len, NULL, NULL);
 	}
-	if (!RETVAL && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+	if (RETVAL && RETVAL != ERROR_MORE_DATA) {
 	    RegCloseKey(remote_lmkey);
 	    RegCloseKey(remote_perfkey);
 	    XSRETURN_NO;
diff -ur libwin32-0.16/Process/Process.pm libwin32-0.171/Process/Process.pm
--- libwin32-0.16/Process/Process.pm	Tue Sep 19 16:37:49 2000
+++ libwin32-0.171/Process/Process.pm	Tue Sep 19 16:39:24 2000
@@ -79,7 +79,8 @@
 
 =head1  DESCRIPTION
 
-This module allows for control of processes in Perl.
+This module provides access to the process control functions in the
+Win32 API.
 
 =head1 METHODS
 
@@ -100,8 +101,8 @@
 
 =item Win32::Process::KillProcess($pid, $exitcode)
 
-Terminates any process identified by $pid.  The process will exit
-with $exitcode.
+Terminates any process identified by $pid.  $exitcode will be set to
+the exit code of the process.
 
 =item $ProcessObj->Suspend()
 
@@ -111,9 +112,9 @@
 
 Resume a suspended process.
 
-=item $ProcessObj->Kill( $ExitCode )
+=item $ProcessObj->Kill( $exitcode )
 
-Kill the associated process, have it die with exit code $ExitCode.
+Kill the associated process, have it terminate with exit code $ExitCode.
 
 =item $ProcessObj->GetPriorityClass($class)
 
@@ -133,19 +134,48 @@
 
 Set the process affinity mask.  Only available on Windows NT.
 
-=item $ProcessObj->GetExitCode( $ExitCode )
+=item $ProcessObj->GetExitCode( $exitcode )
 
 Retrieve the exitcode of the process.
 
-=item $ProcessObj->Wait($Timeout)
+=item $ProcessObj->Wait($timeout)
 
-Wait for the process to die. forever = INFINITE
+Wait for the process to die.  $timeout should be specified in milliseconds.
+To wait forever, specify the constant C<INFINITE>.
 
 =item $ProcessObj->GetProcessID()
 
 Returns the Process ID.
 
 =back
+
+=head1 EXPORTS
+
+The following constants are exported by default.
+
+	CREATE_DEFAULT_ERROR_MODE
+	CREATE_NEW_CONSOLE
+	CREATE_NEW_PROCESS_GROUP
+	CREATE_NO_WINDOW
+	CREATE_SEPARATE_WOW_VDM
+	CREATE_SUSPENDED
+	CREATE_UNICODE_ENVIRONMENT
+	DEBUG_ONLY_THIS_PROCESS
+	DEBUG_PROCESS
+	DETACHED_PROCESS
+	HIGH_PRIORITY_CLASS
+	IDLE_PRIORITY_CLASS
+	INFINITE
+	NORMAL_PRIORITY_CLASS
+	REALTIME_PRIORITY_CLASS
+	THREAD_PRIORITY_ABOVE_NORMAL
+	THREAD_PRIORITY_BELOW_NORMAL
+	THREAD_PRIORITY_ERROR_RETURN
+	THREAD_PRIORITY_HIGHEST
+	THREAD_PRIORITY_IDLE
+	THREAD_PRIORITY_LOWEST
+	THREAD_PRIORITY_NORMAL
+	THREAD_PRIORITY_TIME_CRITICAL
 
 =cut
 
diff -ur libwin32-0.16/Win32.pm libwin32-0.171/Win32.pm
--- libwin32-0.16/Win32.pm	Tue Sep 19 16:37:50 2000
+++ libwin32-0.171/Win32.pm	Tue Sep 19 16:39:25 2000
@@ -6,7 +6,7 @@
 #  included with the latest builds of the ActivePerl distribution.)
 #
 
-$VERSION = $VERSION = '0.16';
+$VERSION = $VERSION = '0.171';
 
 require Exporter;
 require DynaLoader;
End of Patch.