Hi,
----- Original Message ----- 
From: "Daniel Berger" <djberg96 / yahoo.com>
To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
Sent: Friday, August 08, 2003 12:29 PM
Subject: Ruby, MS Windows, extensions and entry points


> Hi all,
>
> I'm trying to write a Ruby extension that would make
> the Etc module functions, such as getpwnam, work on
> Win32 (in roughly the same manner).
>
> The equivalent to the getpwnam call on Win32 is
> NetUserGetInfo().  The only problem is that when I
> wrap this in an extension, the call always fails.  I
> *think* I know why.
>
> Take a look at the C program here (scroll down to the
> example code):
>
>
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netusergetinfo.asp
>
> When I build this program as-is, it works fine.  One
> thing to note, however, is that this program uses
> "wmain" as an entry point instead of "main",
> presumably as a way of handling wide-strings.  Any
> attempt to change the entry point back to main causes
> NetUserGetInfo() to return an unsuccessful result
> (error code 2221).
>
> Consequently, trying to wrap this code in an extension
> causes a similar error, I'm guessing because of the
> main vs wmain issue.
>
> Is there a way around this?  Below is a sample
> extension.
>

It's due to the Unicode Conversion problem.

Try with following code.

Regards,

Park Heesob

/* win32etc.c */
#include "ruby.h"
#include <windows.h>
#include <stdio.h>
#include <lm.h>

#ifndef UNICODE
#define UNICODE
#endif

static VALUE win32etc_getpwnam(VALUE mod, VALUE name)
{
   DWORD dwLevel = 10;
   LPUSER_INFO_10 pBuf = NULL;
   NET_API_STATUS nStatus;
   char *cname = STR2CSTR(name);
   char dest[256];
   wchar_t wszUserName[UNLEN+1];


   VALUE Passwd = rb_struct_define("Passwd","name","comment",0);
   VALUE pstruct = rb_struct_new(Passwd);

   MultiByteToWideChar( CP_ACP, 0, cname,
        strlen(cname)+1, wszUserName,
     sizeof(wszUserName)/sizeof(wszUserName[0]) );


   // Call the NetUserGetInfo function; specify level 10.
   nStatus = NetUserGetInfo(NULL,wszUserName,dwLevel,(LPBYTE *)&pBuf);

   // If the call succeeds, print the user information.
   if (nStatus == NERR_Success)
   {
      if (pBuf != NULL)
      {
  WideCharToMultiByte( CP_ACP, 0, pBuf->usri10_name, -1,
         dest, 256, NULL, NULL );
  rb_struct_aset(pstruct,INT2NUM(0),rb_str_new2(dest));

  WideCharToMultiByte( CP_ACP, 0, pBuf->usri10_comment, -1,
         dest, 256, NULL, NULL );
  rb_struct_aset(pstruct,INT2NUM(1),rb_str_new2(dest));
      }
   }
   else
   {
      rb_warn("NetUserGetInfo() call failed");
   }

   /* Free the allocated memory. */
   if (pBuf != NULL)
   {
      NetApiBufferFree(pBuf);
   }

   return pstruct;
}

void Init_win32etc()
{
   VALUE mEtc = rb_define_module("Win32Etc");

   rb_define_module_function(mEtc, "getpwnam",win32etc_getpwnam, 1);

}