Skip to content

Commit ee7e7fc

Browse files
xenujandubois
authored andcommitted
don't defer loading functions to runtime when it isn't necessary
The removed code existed for two reasons: to support pre-2000 Windows versions and to make the module work on Cygwin without linking (certain) win32 libraries. I don't think there are any reasons not to link them, so I added them to Makefile.PL.
1 parent ab782ea commit ee7e7fc

File tree

2 files changed

+67
-180
lines changed

2 files changed

+67
-180
lines changed

Makefile.PL

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ my %param = (
1313
INSTALLDIRS => ($] >= 5.008004 && $] < 5.012 ? 'perl' : 'site'),
1414
);
1515
$param{NO_META} = 1 if eval "$ExtUtils::MakeMaker::VERSION" >= 6.10_03;
16-
$param{LIBS} = ['-L/lib/w32api -lole32 -lversion'] if $^O eq "cygwin";
16+
17+
if ($^O eq 'cygwin') {
18+
$param{LIBS} = ['-L/lib/w32api -lole32 -lversion -luserenv -lnetapi32']
19+
}
20+
else {
21+
$param{LIBS} = ['-luserenv']
22+
}
1723

1824
WriteMakefile(%param);

Win32.xs

Lines changed: 60 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#define WIN32_LEAN_AND_MEAN
2+
#define _WIN32_WINNT 0x0500
23
#include <wchar.h>
34
#include <wctype.h>
45
#include <windows.h>
56
#include <shlobj.h>
67
#include <wchar.h>
8+
#include <userenv.h>
9+
#include <lm.h>
710

811
#define PERL_NO_GET_CONTEXT
912
#include "EXTERN.h"
@@ -22,22 +25,8 @@
2225

2326
#define GETPROC(fn) pfn##fn = (PFN##fn)GetProcAddress(module, #fn)
2427

25-
typedef BOOL (WINAPI *PFNSHGetSpecialFolderPathW)(HWND, WCHAR*, int, BOOL);
26-
typedef HRESULT (WINAPI *PFNSHGetFolderPathW)(HWND, int, HANDLE, DWORD, LPWSTR);
27-
typedef BOOL (WINAPI *PFNCreateEnvironmentBlock)(void**, HANDLE, BOOL);
28-
typedef BOOL (WINAPI *PFNDestroyEnvironmentBlock)(void*);
2928
typedef int (__stdcall *PFNDllRegisterServer)(void);
3029
typedef int (__stdcall *PFNDllUnregisterServer)(void);
31-
typedef DWORD (__stdcall *PFNNetApiBufferFree)(void*);
32-
typedef DWORD (__stdcall *PFNNetWkstaGetInfo)(LPWSTR, DWORD, void*);
33-
34-
typedef BOOL (__stdcall *PFNOpenProcessToken)(HANDLE, DWORD, HANDLE*);
35-
typedef BOOL (__stdcall *PFNOpenThreadToken)(HANDLE, DWORD, BOOL, HANDLE*);
36-
typedef BOOL (__stdcall *PFNGetTokenInformation)(HANDLE, TOKEN_INFORMATION_CLASS, void*, DWORD, DWORD*);
37-
typedef BOOL (__stdcall *PFNAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD,
38-
DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
39-
typedef BOOL (__stdcall *PFNEqualSid)(PSID, PSID);
40-
typedef void* (__stdcall *PFNFreeSid)(PSID);
4130
typedef BOOL (__stdcall *PFNIsUserAnAdmin)(void);
4231
typedef BOOL (WINAPI *PFNGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD*);
4332
typedef void (WINAPI *PFNGetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
@@ -188,55 +177,33 @@ get_unicode_env(pTHX_ const WCHAR *name)
188177
SV *sv = NULL;
189178
void *env;
190179
HANDLE token;
191-
HMODULE module;
192-
PFNOpenProcessToken pfnOpenProcessToken;
193180

194181
/* Get security token for the current process owner */
195-
module = LoadLibrary("advapi32.dll");
196-
if (!module)
197-
return NULL;
198-
199-
GETPROC(OpenProcessToken);
200-
201-
if (pfnOpenProcessToken == NULL ||
202-
!pfnOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &token))
182+
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &token))
203183
{
204-
FreeLibrary(module);
205184
return NULL;
206185
}
207-
FreeLibrary(module);
208186

209187
/* Create a Unicode environment block for this process */
210-
module = LoadLibrary("userenv.dll");
211-
if (module) {
212-
PFNCreateEnvironmentBlock pfnCreateEnvironmentBlock;
213-
PFNDestroyEnvironmentBlock pfnDestroyEnvironmentBlock;
214-
215-
GETPROC(CreateEnvironmentBlock);
216-
GETPROC(DestroyEnvironmentBlock);
217-
218-
if (pfnCreateEnvironmentBlock && pfnDestroyEnvironmentBlock &&
219-
pfnCreateEnvironmentBlock(&env, token, FALSE))
220-
{
221-
size_t name_len = wcslen(name);
222-
WCHAR *entry = (WCHAR *)env;
223-
while (*entry) {
224-
size_t i;
225-
size_t entry_len = wcslen(entry);
226-
BOOL equal = (entry_len > name_len) && (entry[name_len] == '=');
227-
228-
for (i=0; equal && i < name_len; ++i)
229-
equal = (towupper(entry[i]) == towupper(name[i]));
230-
231-
if (equal) {
232-
sv = wstr_to_sv(aTHX_ entry+name_len+1);
233-
break;
234-
}
235-
entry += entry_len+1;
188+
if (CreateEnvironmentBlock(&env, token, FALSE))
189+
{
190+
size_t name_len = wcslen(name);
191+
WCHAR *entry = (WCHAR *)env;
192+
while (*entry) {
193+
size_t i;
194+
size_t entry_len = wcslen(entry);
195+
BOOL equal = (entry_len > name_len) && (entry[name_len] == '=');
196+
197+
for (i=0; equal && i < name_len; ++i)
198+
equal = (towupper(entry[i]) == towupper(name[i]));
199+
200+
if (equal) {
201+
sv = wstr_to_sv(aTHX_ entry+name_len+1);
202+
break;
236203
}
237-
pfnDestroyEnvironmentBlock(env);
204+
entry += entry_len+1;
238205
}
239-
FreeLibrary(module);
206+
DestroyEnvironmentBlock(env);
240207
}
241208
CloseHandle(token);
242209
return sv;
@@ -367,12 +334,6 @@ XS(w32_IsAdminUser)
367334
dXSARGS;
368335
HMODULE module;
369336
PFNIsUserAnAdmin pfnIsUserAnAdmin;
370-
PFNOpenThreadToken pfnOpenThreadToken;
371-
PFNOpenProcessToken pfnOpenProcessToken;
372-
PFNGetTokenInformation pfnGetTokenInformation;
373-
PFNAllocateAndInitializeSid pfnAllocateAndInitializeSid;
374-
PFNEqualSid pfnEqualSid;
375-
PFNFreeSid pfnFreeSid;
376337
HANDLE hTok;
377338
DWORD dwTokInfoLen;
378339
TOKEN_GROUPS *lpTokInfo;
@@ -388,88 +349,57 @@ XS(w32_IsAdminUser)
388349
* if the process is running with elevated privileges and not just when the
389350
* process owner is a member of the "Administrators" group.
390351
*/
391-
module = LoadLibrary("shell32.dll");
392-
if (module) {
393-
GETPROC(IsUserAnAdmin);
394-
if (pfnIsUserAnAdmin) {
395-
EXTEND(SP, 1);
396-
ST(0) = sv_2mortal(newSViv(pfnIsUserAnAdmin() ? 1 : 0));
397-
FreeLibrary(module);
398-
XSRETURN(1);
399-
}
400-
FreeLibrary(module);
401-
}
402-
403-
module = LoadLibrary("advapi32.dll");
404-
if (!module) {
405-
warn("Cannot load advapi32.dll library");
406-
XSRETURN_UNDEF;
407-
}
408-
409-
GETPROC(OpenThreadToken);
410-
GETPROC(OpenProcessToken);
411-
GETPROC(GetTokenInformation);
412-
GETPROC(AllocateAndInitializeSid);
413-
GETPROC(EqualSid);
414-
GETPROC(FreeSid);
415-
416-
if (!(pfnOpenThreadToken && pfnOpenProcessToken &&
417-
pfnGetTokenInformation && pfnAllocateAndInitializeSid &&
418-
pfnEqualSid && pfnFreeSid))
419-
{
420-
warn("Cannot load functions from advapi32.dll library");
421-
FreeLibrary(module);
422-
XSRETURN_UNDEF;
352+
module = GetModuleHandleA("shell32.dll");
353+
GETPROC(IsUserAnAdmin);
354+
if (pfnIsUserAnAdmin) {
355+
EXTEND(SP, 1);
356+
ST(0) = sv_2mortal(newSViv(pfnIsUserAnAdmin() ? 1 : 0));
357+
XSRETURN(1);
423358
}
424359

425-
if (!pfnOpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hTok)) {
426-
if (!pfnOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hTok)) {
360+
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hTok)) {
361+
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hTok)) {
427362
warn("Cannot open thread token or process token");
428-
FreeLibrary(module);
429363
XSRETURN_UNDEF;
430364
}
431365
}
432366

433-
pfnGetTokenInformation(hTok, TokenGroups, NULL, 0, &dwTokInfoLen);
367+
GetTokenInformation(hTok, TokenGroups, NULL, 0, &dwTokInfoLen);
434368
if (!New(1, lpTokInfo, dwTokInfoLen, TOKEN_GROUPS)) {
435369
warn("Cannot allocate token information structure");
436370
CloseHandle(hTok);
437-
FreeLibrary(module);
438371
XSRETURN_UNDEF;
439372
}
440373

441-
if (!pfnGetTokenInformation(hTok, TokenGroups, lpTokInfo, dwTokInfoLen,
374+
if (!GetTokenInformation(hTok, TokenGroups, lpTokInfo, dwTokInfoLen,
442375
&dwTokInfoLen))
443376
{
444377
warn("Cannot get token information");
445378
Safefree(lpTokInfo);
446379
CloseHandle(hTok);
447-
FreeLibrary(module);
448380
XSRETURN_UNDEF;
449381
}
450382

451-
if (!pfnAllocateAndInitializeSid(&NtAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
383+
if (!AllocateAndInitializeSid(&NtAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
452384
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid))
453385
{
454386
warn("Cannot allocate administrators' SID");
455387
Safefree(lpTokInfo);
456388
CloseHandle(hTok);
457-
FreeLibrary(module);
458389
XSRETURN_UNDEF;
459390
}
460391

461392
iRetVal = 0;
462393
for (i = 0; i < lpTokInfo->GroupCount; ++i) {
463-
if (pfnEqualSid(lpTokInfo->Groups[i].Sid, pAdminSid)) {
394+
if (EqualSid(lpTokInfo->Groups[i].Sid, pAdminSid)) {
464395
iRetVal = 1;
465396
break;
466397
}
467398
}
468399

469-
pfnFreeSid(pAdminSid);
400+
FreeSid(pAdminSid);
470401
Safefree(lpTokInfo);
471402
CloseHandle(hTok);
472-
FreeLibrary(module);
473403

474404
EXTEND(SP, 1);
475405
ST(0) = sv_2mortal(newSViv(iRetVal));
@@ -790,7 +720,6 @@ XS(w32_GetFolderPath)
790720
WCHAR wpath[MAX_PATH+1];
791721
int folder;
792722
int create = 0;
793-
HMODULE module;
794723

795724
if (items != 1 && items != 2)
796725
croak("usage: Win32::GetFolderPath($csidl [, $create])\n");
@@ -799,28 +728,14 @@ XS(w32_GetFolderPath)
799728
if (items == 2)
800729
create = SvTRUE(ST(1)) ? CSIDL_FLAG_CREATE : 0;
801730

802-
module = LoadLibrary("shfolder.dll");
803-
if (module) {
804-
PFNSHGetFolderPathW pfnw;
805-
pfnw = (PFNSHGetFolderPathW)GetProcAddress(module, "SHGetFolderPathW");
806-
if (pfnw && SUCCEEDED(pfnw(NULL, folder|create, NULL, 0, wpath))) {
807-
FreeLibrary(module);
808-
ST(0) = wstr_to_ansipath(aTHX_ wpath);
809-
XSRETURN(1);
810-
}
811-
FreeLibrary(module);
731+
if (SUCCEEDED(SHGetFolderPathW(NULL, folder|create, NULL, 0, wpath))) {
732+
ST(0) = wstr_to_ansipath(aTHX_ wpath);
733+
XSRETURN(1);
812734
}
813735

814-
module = LoadLibrary("shell32.dll");
815-
if (module) {
816-
PFNSHGetSpecialFolderPathW pfnw;
817-
pfnw = (PFNSHGetSpecialFolderPathW)GetProcAddress(module, "SHGetSpecialFolderPathW");
818-
if (pfnw && pfnw(NULL, wpath, folder, !!create)) {
819-
FreeLibrary(module);
820-
ST(0) = wstr_to_ansipath(aTHX_ wpath);
821-
XSRETURN(1);
822-
}
823-
FreeLibrary(module);
736+
if (SHGetSpecialFolderPathW(NULL, wpath, folder, !!create)) {
737+
ST(0) = wstr_to_ansipath(aTHX_ wpath);
738+
XSRETURN(1);
824739
}
825740

826741
/* SHGetFolderPathW() and SHGetSpecialFolderPathW() may fail on older
@@ -1119,65 +1034,31 @@ XS(w32_NodeName)
11191034
XS(w32_DomainName)
11201035
{
11211036
dXSARGS;
1122-
HMODULE module = LoadLibrary("netapi32.dll");
1123-
PFNNetApiBufferFree pfnNetApiBufferFree = NULL;
1124-
PFNNetWkstaGetInfo pfnNetWkstaGetInfo = NULL;
1037+
char dname[256];
1038+
DWORD dnamelen = sizeof(dname);
1039+
WKSTA_INFO_100 *pwi;
1040+
DWORD retval;
11251041

11261042
if (items)
11271043
Perl_croak(aTHX_ "usage: Win32::DomainName()");
1128-
if (module) {
1129-
GETPROC(NetApiBufferFree);
1130-
GETPROC(NetWkstaGetInfo);
1131-
}
1044+
11321045
EXTEND(SP,1);
1133-
if (module && pfnNetWkstaGetInfo && pfnNetApiBufferFree) {
1134-
/* this way is more reliable, in case user has a local account. */
1135-
char dname[256];
1136-
DWORD dnamelen = sizeof(dname);
1137-
struct {
1138-
DWORD wki100_platform_id;
1139-
LPWSTR wki100_computername;
1140-
LPWSTR wki100_langroup;
1141-
DWORD wki100_ver_major;
1142-
DWORD wki100_ver_minor;
1143-
} *pwi;
1144-
DWORD retval;
1145-
retval = pfnNetWkstaGetInfo(NULL, 100, &pwi);
1146-
/* NERR_Success *is* 0*/
1147-
if (retval == 0) {
1148-
if (pwi->wki100_langroup && *(pwi->wki100_langroup)) {
1149-
WideCharToMultiByte(CP_ACP, 0, pwi->wki100_langroup,
1150-
-1, (LPSTR)dname, dnamelen, NULL, NULL);
1151-
}
1152-
else {
1153-
WideCharToMultiByte(CP_ACP, 0, pwi->wki100_computername,
1154-
-1, (LPSTR)dname, dnamelen, NULL, NULL);
1155-
}
1156-
pfnNetApiBufferFree(pwi);
1157-
FreeLibrary(module);
1158-
XSRETURN_PV(dname);
1159-
}
1160-
FreeLibrary(module);
1161-
SetLastError(retval);
1162-
}
1163-
else {
1164-
/* Win95 doesn't have NetWksta*(), so do it the old way */
1165-
char name[256];
1166-
DWORD size = sizeof(name);
1167-
if (module)
1168-
FreeLibrary(module);
1169-
if (GetUserName(name,&size)) {
1170-
char sid[ONE_K_BUFSIZE];
1171-
DWORD sidlen = sizeof(sid);
1172-
char dname[256];
1173-
DWORD dnamelen = sizeof(dname);
1174-
SID_NAME_USE snu;
1175-
if (LookupAccountName(NULL, name, (PSID)&sid, &sidlen,
1176-
dname, &dnamelen, &snu)) {
1177-
XSRETURN_PV(dname); /* all that for this */
1178-
}
1179-
}
1046+
1047+
retval = NetWkstaGetInfo(NULL, 100, (LPBYTE*)&pwi);
1048+
/* NERR_Success *is* 0*/
1049+
if (retval == 0) {
1050+
if (pwi->wki100_langroup && *(pwi->wki100_langroup)) {
1051+
WideCharToMultiByte(CP_ACP, 0, pwi->wki100_langroup,
1052+
-1, (LPSTR)dname, dnamelen, NULL, NULL);
1053+
}
1054+
else {
1055+
WideCharToMultiByte(CP_ACP, 0, pwi->wki100_computername,
1056+
-1, (LPSTR)dname, dnamelen, NULL, NULL);
1057+
}
1058+
NetApiBufferFree(pwi);
1059+
XSRETURN_PV(dname);
11801060
}
1061+
SetLastError(retval);
11811062
XSRETURN_UNDEF;
11821063
}
11831064

0 commit comments

Comments
 (0)