Some attempts by C # to access Win 32

Source: Internet
Author: User

Using C # to call the win + API Most of the time basically only involves the conversion of the parameter type, but encountered some parsing traversal difficulties when encountering the win + API return LPVOID *lpbuff. Lpbuff is a two-dimensional pointer, and *lpbuff is the first address of an array that points to its contents, which can be accessed directly through an array subscript in C + +. In C #, however, there are the following issues:

    1. The structure pointer can not be forced to change as the C + +;
    2. No direct value operation such as (*lpbuff) [0] can be performed;
    3. Unable to perform pointer accumulation/decrement traversal operations such as lptemp++;

In the related documentation, you can see that C # encapsulates pointers using IntPtr, and Marshal provides some quick ways to implement *lpstruct to structs. But there are still some tricks to be IntPtr on the Traverse. Take the win + API for network groups as an example:

Win + API:

struct _localgroup_info_1 {  lpwstr lgrpi1_name;   *plocalgroup_info_1, *lplocalgroup_info_1;net_api_status netlocalgroupenum (  _in_    lpcwstr    ServerName,  _in_    DWORD level      ,  _out_   lpbyte     *bufptr,  _in_    DWORD      Prefmaxlen,  _out_   lpdword    entriesread,  _out_   lpdword    totalentries,  _ Inout_ pdword_ptr resumehandle);

to C #:

[StructLayout (layoutkind.sequential)] Internal struct Localgroup_info_1        {           [MarshalAs (UNMANAGEDTYPE.LPWSTR)]            publiclgrpi1_name;
[MarshalAs (UNMANAGEDTYPE.LPWSTR)]
       public lgrpi1_comment;

}
DllImport ("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError =true)]
Internal extern Static UINTNetlocalgroupenum ([MarshalAs (UNMANAGEDTYPE.LPWSTR)]stringservername,intLevel , outIntPtr BufPtr,intPrefmaxlen, out intEntriesread, out intTotalentries,ref intResume_handle);

This function gets all network groups on the local machine, and the group structure contains the name of the group and the description of the group. The Netlocalgroupenum function is internally assigned the BUFPTR, which is returned to the caller. The C # code for Getgrouplist is as follows:

 Public Staticienumerable<Dynamic> Getgrouplist ( ThisVPN v)//function code basically copy from [8] {intSize =4096;//Start with 4k            varBufPtr =NewIntPtr (size); intLevel =0; intPrefmaxlen =1023; intEntriesread =0; intTotalentries =0; intResume_handle =0; UINTErr =0;  Do{Err=Netlocalgroupenum (NULL, Level, outbufptr, Prefmaxlen, outEntriesread, outTotalentries,refresume_handle); Switch(err) {//If There is more data, double the size of the buffer ...                     CaseNerr_buftoosmall://Nerr_buftoosmall                     CaseError_more_data://Error_more_dataSize *=2; BufPtr=NewIntPtr (size); Prefmaxlen= Size-1;//increase the size want read as wellResume_handle =0;//and Reset the Resume_handle or you'll just pick up where you left off.                         Break;  Case 2351://Nerr_invalidcomputer                        Throw NewException ("Nerr_invalidcomputer");  Case 0://nerr_success                    default:                         Break; }            }             while(Err = = ERROR_MORE_DATA);//And start over//group_info_0 group=new group_info_0 ();//See user type aboveLocalgroup_info_1 Group; varGlist =Newlist<Dynamic>(Entriesread); varITER =BufPtr;  for(inti =0; i < Entriesread; i++) {Group= marshal.ptrtostructure<localgroup_info_1>(ITER); Glist. ADD (New{Name =Group.lgrpi1_name, Commet=group.lgrpi1_comment}); ITER= (INTPTR) (ITER). ToInt64 () + marshal.sizeof<localgroup_info_1>());            } netapibufferfree (BUFPTR); returnglist; }

where group = marshal.ptrtostructure<localgroup_info_1> (ITER); Responsible for converting byte[] to struct; iter = (INTPTR) (ITER). ToInt64 () + marshal.sizeof<localgroup_info_1> ()); Responsible for traversal.

During the traversal, ITER = (INTPTR) (ITER). ToInt64 () + marshal.sizeof<localgroup_info_1> ()) Gets the array of pointer arrays the function of the base address is ITER. ToInt64 (). Whether the compilation is set to X86 or X64,toint64 and ToInt32 can be used under any platform. However, the ToInt32 may overflow in 64-bit systems. ToInt32 and ToInt64 are independent of the specific pointer type (int32* or int64*), which is only a logical integer and is the value of its base address. IntPtr also has an extension method ToInt () that can be tested for traversal.

The Win32 API returns the traversal of the buffer as above, but after several tests it is found that the method is not working stably. A memory read error occurs when comment = NULL exists in the returned Group_info_1 instance. In the case of an error, there may be a read null error, or it may be that the next pass error occurs after reading to NULL. Given the possibility that an error might be declared as [MarshalAs (UNMANAGEDTYPE.LPWSTR)], it is decided to follow some other notation, declaring its string pointer lpcwstr as IntPtr for processing.

Change as follows:

[StructLayout (layoutkind.sequential)]Internal structlocalgroup_info_1{    //[MarshalAs (UNMANAGEDTYPE.LPWSTR)]//public string Grpi1_name;    Public    IntPtr grpi1_name; //[MarshalAs (UNMANAGEDTYPE.LPWSTR)]//public string grpi1_comment;     Public IntPtr grpi1_comment;}//parsing for(inti =0; i < Entriesread; i++) {Group= marshal.ptrtostructure<localgroup_info_1>(ITER); glist. ADD (  new {Name = Marshal.ptrtostringuni (group.grpi1_name), Commet = Marshal.ptrtostringuni (group.grpi1_comment)}); ITER= (INTPTR) (ITER). ToInt64 () + marshal.sizeof<localgroup_info_1>());}

It's still wrong, but it's getting better. Entriesread returns there are currently 19 groups, and a view of Windows "Management" does also exist in 19 groups. However, as with the LPWSTR definition, when the 9th group appears comment = null, all subsequent groups name & comment are null and then the 18th record times are wrong. It is really strange that all groups have a description from the Windows user group, but no descriptive information is found while traversing.

By carefully reviewing the traversal records, we find that the traversal is all user names, not descriptions. It occurred to me that there was an error in the category of user group information, and sure enough, the error section uses level 0 of the sample code, and the level should be set to 1. After setting to 1, the original code does not work correctly, prompting for more memory. The original code is modified to work correctly and indicates one of the errors. (Sample code from [8])

  Public Staticienumerable<Dynamic> Getgrouplist ( ThisVPN v) {            varBufPtr = IntPtr.Zero;//In [8], where new IntPtr (size) is the default handle value for INTPTR, not the buffer size. In the case of low memory, it is not possible to increase the memory by enlarging the size. Prefmaxlen is the size of the buffer.             UINTLevel =1; UINTPrefmaxlen =max_preferred_length; //Can be set to maximum here and do not need to worry too much about memory issues. This is the maximum receive value, and the memory win 32 is created dynamically.            * Unless you don't want to get so much data at once. UINTEntriesread =0; UINTTotalentries =0; UINTResume_handle =0; UINTErr =0; Err=Netlocalgroupenum (NULL, Level,refbufptr, Prefmaxlen,refEntriesread,refTotalentries,refresume_handle);            Localgroup_info_1 Group; varGlist =Newlist<Dynamic>(Entriesread.            ToInt ()); varITER =BufPtr;  for(inti =0; i < Entriesread; i++) {Group= marshal.ptrtostructure<localgroup_info_1>(ITER); Glist. ADD (New{Name =Group.lgrpi1_name, Comment=group.lgrpi1_comment}); ITER= (INTPTR) (ITER). ToInt64 () + marshal.sizeof<localgroup_info_1>());            } netapibufferfree (BUFPTR); returnglist; }

Working correctly, the output is as follows:

Access Control Assistance Operators, members of this group can remotely query the authorization properties and permissions for resources on this computer. Administrators, the administrator to the computer/The domain has unrestricted full access to backup Operators, which is used in order to back up or restore files in place of security restrictions cryptographic Operators, authorizing members to perform cryptographic operations. Distributed COM Users, members allow you to start, activate, and use distributed COM objects on this computer. Event Log Readers, a member of this group can read guests from the local computer, by default, the guest has equal access to the members of the user group, but the guest account has more restrictions Hyper-V Administrators, members of this group have the hyper-full and unrestricted access to all features of the V. Iis_iusrs, the built-in group used by Internet information services. Network configuration Operators, members of this group have some administrative rights to manage the configurations of the networking features performance log Users, members of this group can schedule performance counter logging, enable trace logging providers, As well as local or remote access to this computer to collect event Trace records performance Monitor users, members of this group can access performance counter data from both local and remote power users, including advanced user to backward-compatible, Advanced users have limited administrative privileges remote Desktop users, members of this group are granted remote login permissions for remote Management Users, members of this group can be managed through the management Protocol (for example, WS through the Windows Remote Management Service -Management) access to WMI resources. This applies only to WMI namespaces that grant user access. Replicator, the File replication system Managed Accounts Group is supported in the domain, and the members of this group are managed by the system. Users to prevent intentional or unintentional system-wide changes, but can run most applications __vmware__, VMware user Group

Reference

[1] https://msdn.microsoft.com/zh-cn/library/fzhhdwae%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

[2] Https://msdn.microsoft.com/zh-cn/library/system.intptr.subtract (v=vs.110). aspx

[3] pointer type, https://msdn.microsoft.com/zh-cn/library/aa664771 (v=vs.71). aspx

[4] pointer type (C # Programming Guide), https://msdn.microsoft.com/zh-cn/library/y31yhkeb.aspx

[5] Type support, Https://msdn.microsoft.com/zh-cn/library/c300dbaa (v=vs.90). aspx

[6] Platform invoke tutorial, https://msdn.microsoft.com/zh-cn/library/aa288468 (v=vs.71). aspx

[7] A wiki for. NET developers, http://www.pinvoke.net/

[8] Netlocalgroupenum, Http://www.pinvoke.net/default.aspx/netapi32.NetLocalGroupEnum

Some attempts by C # to access Win 32

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.