[python-win32] Where are the Lsa* functions?

Jorgensen, Jens jens.jorgensen@tallan.com
Wed, 13 Jun 2001 12:02:14 -0500


This is a multi-part message in MIME format.
--------------017387157DB7E27338FCC5EF
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I was going to suggest using ADSI but I notice that the ADSI user object doesn't in fact support adding the SeLogonServiceRight. Indeed the best approach for you would be to build a custom module. Creating a custom module is very easy if you have MSVC, if you don't it's a little tougher. No access to a win32 compiler you say? You don't have access to the internet to download cygwin? Cygwin is a freely available set of tools which basically gives you all the fine Gnu tools one expects in Linux. Along with this it gives you gcc, the Gnu C/C++ compiler. With this you can create extensions. Get this from www.cygwin.com. There are instructions for building extensions with cygwin at:

http://starship.python.net/crew/kernr/mingw32/Notes.html

I didn't follow all of them. I just installed cygwin and then used his lib2def.py tool and copied his dllwrap command line. I did not install the other patches recommended. Things seemed to work find without them. Anyhow more on that below.

The first step is to create your C/C++ source file. The easiest way to generate this I think is to use modulator.py. The only thing I don't like about this script is it generates K&R C function definitions which I have to then fix. Other than that this is a really nice too. It's a Tk-based GUI that let's you define what functions and objects you want your module to have and then generates all the stubs for you. I've attached one I quickly created.

Now, I'm assuming you've already installed cygwin. The main thing in your way now is getting a library to link to for Python21. The .lib which comes with ActiveState's install works with MSVC and you need a GNU one. This is a bit trickier than it should be. There's a utility I've attached called lib2def.py which I grabed from some site, I forget which. You'll need to open it up and replace python20 everywhere with python21. Then run it like this:

python lib2def.py c:/Python21/libs/python21.lib > python21.def

Then you'll use dlltool like this:

dlltool.exe --dllname python21.dll --def python21.def --output-lib libpython21.a

Now this library is made you can store it away in the cygwin /usr/lib directory. Where this is depends on where you installed cygwin but if you're running the cygwin shell which gives you unix-style paths you can just say 'mv libpython21.a /usr/lib/'. Now, at this point in an ideal world distutils would just do all the work for you. I tried this and was able to build the module but it got hung up when I ran it. So, instead I just did a manual compile with:

g++ -I/c/Python20/Include -c lsa_mod.c

Now you need to build your .def file which says which symbols to export from your DLL. Put this into a file called LSA.def:

LIBRARY LSA.pyd
EXPORTS
initLSA

And now (take a deep breath) you're ready to run dllwrap to generate the DLL. How did I come up with this command line? I stole it from above web page:

dllwrap.exe --dllname LSA.pyd --driver-name gcc --def build/temp.win32-2.0/Release/LSA.def -o LSA.pyd lsa_mod.o -s --entry _DllMain@12 --target=i386-mingw32 -L/usr/local/lib -lpython20

The above is ugly I know. I don't fully understand all of it either. In fact, this is the first time I've ever seen dllwrap. Note that in the above I have '-L/usr/local/lib -lpython20' because I built mine against python 2.0 and put my libpython20.a into /usr/local/lib. You can modify this to suit wherever you put it.

I tested the above and it seems to work. That is, I verified that I could load the resulting module and call LSA.LsaOpenPolicy although I didn't really know what to pass it so I didn't get a handle. I should point out that it looks like you'll at least need LsaClose in addition to the functions you named. If it where me I'd probably create an object which would encapsulate the LSA handle and then have methods on that. I didn't do that in the simple module source I generated. I leave that as an exercise for the reader.

So, that should be enough to get you going. I would've just built you the module myself but I'm still using Python 2.0. Why haven't I upgraded? Actually I haven't upgraded because I'm using numerous extension modules I've built against Python 2.0. To upgrade I'll have to rebuild them all and I haven't had time yet.

Good luck, if you get stuck you can email me.

"Jeffrey C. Ollie" wrote:

> I'm just getting started doing some win32 programming with the win32
> extensions from ActivePython 2.1 build 210.  I've never done any win32
> programming before but I've been able to figure things out from MSDN
> and the sample win32 code included with ActivePython.
>
> The task that I'm faced with now is to:
>
> 1. Copy a set of files from a network drive to the local workstation drive.
> 2. Create a local user account on a Windows NT 4.0 workstation.
> 3. Add the SeLogonServiceRight to the local user account.
> 4. Install three services, one of which logs on as the aforementioned account.
> 5. Be able to undo the previous steps.
>
> I've been able to accomplish everything that I need so far except to
> be able to add the SeLogonServiceRight to the local user account.
> From digging through MSDN, it appears that I need the LsaOpenPolicy,
> LsaAddAccountRights, and LsaRemoveAccountRights functions.  These
> functions do not appear to be defined in the win32 extensions (I've
> even grepped through the source code).
>
> I've been able to work around the lack of the Lsa* functions by
> running an external command-line program that I downloaded off the net
> (see <http://www.franzo.co.nz/hansson/grant.htm>).  It'd be much
> cleaner though if I could add the rights without calling an external
> program.  Is there any chance that the Lsa* functions will get added
> to the win32 extensions in the near future?  I don't have access to a
> win32 compiler - I'd consider attempting to add the Lsa* functions
> myself if I did.
>
> Jeff
>
> _______________________________________________
> Python-win32 mailing list
> Python-win32@python.org
> http://mail.python.org/mailman/listinfo/python-win32

--
Jens B. Jorgensen
jens.jorgensen@tallan.com



--------------017387157DB7E27338FCC5EF
Content-Type: application/x-unknown-content-type-cppfile;
 name="lsa_mod.cpp"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="lsa_mod.cpp"

DQojaW5jbHVkZSA8d2luZG93cy5oPg0KI2luY2x1ZGUgPHczMmFwaS93dHlwZXMuaD4NCiNpbmNs
dWRlIDx3MzJhcGkvYmFzZXRzZC5oPg0KI2luY2x1ZGUgPHczMmFwaS93aW5udC5oPg0KLyojaW5j
bHVkZSA8dzMyYXBpL250ZGVmLmg+Ki8NCnR5cGVkZWYgc3RydWN0IF9RVU9UQV9MSU1JVFMgew0K
CVNJWkVfVCBQYWdlZFBvb2xMaW1pdDsNCglTSVpFX1QgTm9uUGFnZWRQb29sTGltaXQ7DQoJU0la
RV9UIE1pbmltdW1Xb3JraW5nU2V0U2l6ZTsNCglTSVpFX1QgTWF4aW11bVdvcmtpbmdTZXRTaXpl
Ow0KCVNJWkVfVCBQYWdlZmlsZUxpbWl0Ow0KCUxBUkdFX0lOVEVHRVIgVGltZUxpbWl0Ow0KfSBR
VU9UQV9MSU1JVFMsKlBRVU9UQV9MSU1JVFM7DQojaW5jbHVkZSA8dzMyYXBpL250c2VjYXBpLmg+
DQojaW5jbHVkZSA8c3RyaW5nLmg+DQojaW5jbHVkZSAiUHl0aG9uLmgiDQoNCnN0YXRpYyBQeU9i
amVjdCAqRXJyb3JPYmplY3Q7DQoNCi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tICovDQoNCnN0YXRpYyBjaGFyIExTQV9Mc2FPcGVuUG9saWN5
X19kb2NfX1tdID0NCiIiDQo7DQoNCnN0YXRpYyBQeU9iamVjdCAqDQpMU0FfTHNhT3BlblBvbGlj
eShQeU9iamVjdCAqc2VsZiwgUHlPYmplY3QgKmFyZ3MpDQp7DQogICAgVU5JQ09ERV9TVFJJTkcg
KndzOw0KICAgIExTQV9PQkpFQ1RfQVRUUklCVVRFUyBsb2E7DQogICAgTFNBX0hBTkRMRSBoOw0K
ICAgIEFDQ0VTU19NQVNLIGFtID0gUE9MSUNZX0NSRUFURV9BQ0NPVU5UOw0KICAgIG1lbXNldCgm
bG9hLCAwLCBzaXplb2YobG9hKSk7DQogICAgaWYgKCFQeUFyZ19QYXJzZVR1cGxlKGFyZ3MsICJ1
IiwgJndzKSkNCiAgICAgICAgcmV0dXJuIE5VTEw7DQogICAgaWYgKExzYU9wZW5Qb2xpY3kod3Ms
ICZsb2EsIGFtLCAmaCkgIT0gRVJST1JfU1VDQ0VTUykgew0KICAgICAgICBQeUVycl9TZXRTdHJp
bmcoUHlFeGNfT1NFcnJvciwgIm9wZW4gZmFpbGVkIik7DQogICAgICAgIHJldHVybiBOVUxMOw0K
ICAgIH0NCiAgICByZXR1cm4gUHlJbnRfRnJvbUxvbmcoKGxvbmcpIGgpOw0KfQ0KDQpzdGF0aWMg
Y2hhciBMU0FfTHNhQWRkQWNjb3VudFJpZ2h0c19fZG9jX19bXSA9DQoiIg0KOw0KDQpzdGF0aWMg
UHlPYmplY3QgKg0KTFNBX0xzYUFkZEFjY291bnRSaWdodHMoUHlPYmplY3QgKnNlbGYsIFB5T2Jq
ZWN0ICphcmdzKQ0Kew0KDQoJaWYgKCFQeUFyZ19QYXJzZVR1cGxlKGFyZ3MsICIiKSkNCgkJcmV0
dXJuIE5VTEw7DQoJUHlfSU5DUkVGKFB5X05vbmUpOw0KCXJldHVybiBQeV9Ob25lOw0KfQ0KDQpz
dGF0aWMgY2hhciBMU0FfTHNhUmVtb3ZlQWNjb3VudFJpZ2h0c19fZG9jX19bXSA9DQoiIg0KOw0K
DQpzdGF0aWMgUHlPYmplY3QgKg0KTFNBX0xzYVJlbW92ZUFjY291bnRSaWdodHMoUHlPYmplY3Qg
KnNlbGYsIFB5T2JqZWN0ICphcmdzKQ0Kew0KDQoJaWYgKCFQeUFyZ19QYXJzZVR1cGxlKGFyZ3Ms
ICIiKSkNCgkJcmV0dXJuIE5VTEw7DQoJUHlfSU5DUkVGKFB5X05vbmUpOw0KCXJldHVybiBQeV9O
b25lOw0KfQ0KDQovKiBMaXN0IG9mIG1ldGhvZHMgZGVmaW5lZCBpbiB0aGUgbW9kdWxlICovDQoN
CnN0YXRpYyBzdHJ1Y3QgUHlNZXRob2REZWYgTFNBX21ldGhvZHNbXSA9IHsNCgl7IkxzYU9wZW5Q
b2xpY3kiLAkoUHlDRnVuY3Rpb24pTFNBX0xzYU9wZW5Qb2xpY3ksCU1FVEhfVkFSQVJHUywJTFNB
X0xzYU9wZW5Qb2xpY3lfX2RvY19ffSwNCiB7IkxzYUFkZEFjY291bnRSaWdodHMiLAkoUHlDRnVu
Y3Rpb24pTFNBX0xzYUFkZEFjY291bnRSaWdodHMsCU1FVEhfVkFSQVJHUywJTFNBX0xzYUFkZEFj
Y291bnRSaWdodHNfX2RvY19ffSwNCiB7IkxzYVJlbW92ZUFjY291bnRSaWdodHMiLAkoUHlDRnVu
Y3Rpb24pTFNBX0xzYVJlbW92ZUFjY291bnRSaWdodHMsCU1FVEhfVkFSQVJHUywJTFNBX0xzYVJl
bW92ZUFjY291bnRSaWdodHNfX2RvY19ffSwNCiANCgl7TlVMTCwJIChQeUNGdW5jdGlvbilOVUxM
LCAwLCBOVUxMfQkJLyogc2VudGluZWwgKi8NCn07DQoNCg0KLyogSW5pdGlhbGl6YXRpb24gZnVu
Y3Rpb24gZm9yIHRoZSBtb2R1bGUgKCptdXN0KiBiZSBjYWxsZWQgaW5pdExTQSkgKi8NCg0Kc3Rh
dGljIGNoYXIgTFNBX21vZHVsZV9kb2N1bWVudGF0aW9uW10gPSANCiIiDQo7DQoNCmV4dGVybiAi
QyIgdm9pZA0KaW5pdExTQSgpDQp7DQoJUHlPYmplY3QgKm0sICpkOw0KDQoJLyogQ3JlYXRlIHRo
ZSBtb2R1bGUgYW5kIGFkZCB0aGUgZnVuY3Rpb25zICovDQoJbSA9IFB5X0luaXRNb2R1bGU0KCJM
U0EiLCBMU0FfbWV0aG9kcywNCgkJTFNBX21vZHVsZV9kb2N1bWVudGF0aW9uLA0KCQkoUHlPYmpl
Y3QqKU5VTEwsUFlUSE9OX0FQSV9WRVJTSU9OKTsNCg0KCS8qIEFkZCBzb21lIHN5bWJvbGljIGNv
bnN0YW50cyB0byB0aGUgbW9kdWxlICovDQoJZCA9IFB5TW9kdWxlX0dldERpY3QobSk7DQoJRXJy
b3JPYmplY3QgPSBQeVN0cmluZ19Gcm9tU3RyaW5nKCJMU0EuZXJyb3IiKTsNCglQeURpY3RfU2V0
SXRlbVN0cmluZyhkLCAiZXJyb3IiLCBFcnJvck9iamVjdCk7DQoNCgkvKiBYWFhYIEFkZCBjb25z
dGFudHMgaGVyZSAqLw0KCQ0KCS8qIENoZWNrIGZvciBlcnJvcnMgKi8NCglpZiAoUHlFcnJfT2Nj
dXJyZWQoKSkNCgkJUHlfRmF0YWxFcnJvcigiY2FuJ3QgaW5pdGlhbGl6ZSBtb2R1bGUgTFNBIik7
DQp9DQoNCg==

--------------017387157DB7E27338FCC5EF
Content-Type: text/plain; charset=us-ascii;
 name="lib2def.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="lib2def.py"

import re
import sys
import os
import string

__doc__ = """This module generates a DEF file from the symbols in
an MSVC-compiled DLL import library.  It correctly discriminates between
data and functions.  The data is collected from the output of the program
nm(1).

Usage:
    python lib2def.py [libname.lib] [output.def]
or
    python lib2def.py [libname.lib] > output.def

libname.lib defaults to python20.lib and output.def defaults to stdout

Author: Robert Kern <kernr@mail.ncifcrf.gov>
Last Update: April 30, 1999
"""

__version__ = '0.1a'

DEFAULT_NM = 'nm -Cs'

DEF_HEADER = """LIBRARY		Python20.dll
;CODE		PRELOAD MOVEABLE DISCARDABLE
;DATA		PRELOAD SINGLE

EXPORTS
"""
# the header of the DEF file

FUNC_RE = re.compile(r"^(.*) in python20\.dll", re.MULTILINE)
DATA_RE = re.compile(r"^_imp__(.*) in python20\.dll", re.MULTILINE)

def parse_cmd():
    """Parses the command-line arguments.

libfile, deffile = parse_cmd()"""
    if len(sys.argv) == 3:
        if sys.argv[1][-4:] == '.lib' and sys.argv[2][-4:] == '.def':
            libfile, deffile = sys.argv[1:]
        elif sys.argv[1][-4:] == '.def' and sys.argv[2][-4:] == '.lib':
            deffile, libfile = sys.argv[1:]
        else:
            print "I'm assuming that your first argument is the library\nand the second is the DEF file."
    elif len(sys.argv) == 2:
        if sys.argv[1][-4:] == '.def':
            deffile = sys.argv[1]
            libfile = 'python20.lib'
        elif sys.argv[1][-4:] == '.lib':
            deffile = None
            libfile = sys.argv[1]
    else:
        libfile = 'python20.lib'
        deffile = None
    return libfile, deffile

def getnm(nm_cmd = 'nm -Cs python20.lib'):
    """Returns the output of nm_cmd via a pipe.

nm_output = getnam(nm_cmd = 'nm -Cs py_lib')"""
    f = os.popen(nm_cmd)
    nm_output = f.read()
    f.close()
    return nm_output

def parse_nm(nm_output):
    """Returns a tuple of lists: dlist for the list of data
symbols and flist for the list of function symbols.

dlist, flist = parse_nm(nm_output)"""
    data = DATA_RE.findall(nm_output)
    func = FUNC_RE.findall(nm_output)

    flist = []
    for sym in data:
        if sym in func and (sym[:2] == 'Py' or sym[:3] == '_Py' or sym[:4] == 'init'):
            flist.append(sym)

    dlist = []
    for sym in data:
        if sym not in flist and (sym[:2] == 'Py' or sym[:3] == '_Py'):
            dlist.append(sym)
            
    dlist.sort()
    flist.sort()
    return dlist, flist

def output_def(dlist, flist, header, file = sys.stdout):
    """Outputs the final DEF file to a file defaulting to stdout.

output_def(dlist, flist, header, file = sys.stdout)"""
    for data_sym in dlist:
        header = header + '\t%s DATA\n' % data_sym
    header = header + '\n' # blank line
    for func_sym in flist:
        header = header + '\t%s\n' % func_sym
    file.write(header)

if __name__ == '__main__':
    libfile, deffile = parse_cmd()
    if deffile == None:
        deffile = sys.stdout
    else:
        deffile = open(deffile, 'w')
    nm_cmd = '%s %s' % (DEFAULT_NM, libfile)
    nm_output = getnm(nm_cmd)
    dlist, flist = parse_nm(nm_output)
    output_def(dlist, flist, DEF_HEADER, deffile)

--------------017387157DB7E27338FCC5EF--