7 #define SE_SHUTDOWN_NAMEA "SeShutdownPrivilege"
8 #define SE_SHUTDOWN_NAMEW L"SeShutdownPrivilege"
10 typedef BOOL (WINAPI *PFNSHGetSpecialFolderPath)(HWND, char*, int, BOOL);
11 typedef HRESULT (WINAPI *PFNSHGetFolderPath)(HWND, int, HANDLE, DWORD, LPTSTR);
12 #ifndef CSIDL_FLAG_CREATE
13 # define CSIDL_FLAG_CREATE 0x8000
16 XS(w32_ExpandEnvironmentStrings)
25 croak("usage: Win32::ExpandEnvironmentStrings($String);\n");
27 lpSource = (char *)SvPV(ST(0), n_a);
30 WCHAR wSource[MAX_PATH+1];
32 A2WHELPER(lpSource, wSource, sizeof(wSource));
33 dwDataLen = ExpandEnvironmentStringsW(wSource, wbuffer, sizeof(wbuffer)/2);
34 W2AHELPER(wbuffer, buffer, sizeof(buffer));
37 dwDataLen = ExpandEnvironmentStringsA(lpSource, (char*)buffer, sizeof(buffer));
39 XSRETURN_PV((char*)buffer);
46 BOOL (__stdcall *pfnOpenThreadToken)(HANDLE hThr, DWORD dwDesiredAccess,
47 BOOL bOpenAsSelf, PHANDLE phTok);
48 BOOL (__stdcall *pfnOpenProcessToken)(HANDLE hProc, DWORD dwDesiredAccess,
50 BOOL (__stdcall *pfnGetTokenInformation)(HANDLE hTok,
51 TOKEN_INFORMATION_CLASS TokenInformationClass,
52 LPVOID lpTokInfo, DWORD dwTokInfoLen,
54 BOOL (__stdcall *pfnAllocateAndInitializeSid)(
55 PSID_IDENTIFIER_AUTHORITY pIdAuth,
56 BYTE nSubAuthCount, DWORD dwSubAuth0,
57 DWORD dwSubAuth1, DWORD dwSubAuth2,
58 DWORD dwSubAuth3, DWORD dwSubAuth4,
59 DWORD dwSubAuth5, DWORD dwSubAuth6,
60 DWORD dwSubAuth7, PSID pSid);
61 BOOL (__stdcall *pfnEqualSid)(PSID pSid1, PSID pSid2);
62 PVOID (__stdcall *pfnFreeSid)(PSID pSid);
65 TOKEN_GROUPS *lpTokInfo;
66 SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY;
73 croak("usage: Win32::IsAdminUser()");
75 /* There is no concept of "Administrator" user accounts on Win9x systems,
76 so just return true. */
77 memset(&osver, 0, sizeof(OSVERSIONINFO));
78 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
80 if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
83 hAdvApi32 = LoadLibrary("advapi32.dll");
85 warn("Cannot load advapi32.dll library");
89 pfnOpenThreadToken = (BOOL (__stdcall *)(HANDLE, DWORD, BOOL, PHANDLE))
90 GetProcAddress(hAdvApi32, "OpenThreadToken");
91 pfnOpenProcessToken = (BOOL (__stdcall *)(HANDLE, DWORD, PHANDLE))
92 GetProcAddress(hAdvApi32, "OpenProcessToken");
93 pfnGetTokenInformation = (BOOL (__stdcall *)(HANDLE,
94 TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD))
95 GetProcAddress(hAdvApi32, "GetTokenInformation");
96 pfnAllocateAndInitializeSid = (BOOL (__stdcall *)(
97 PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD,
98 DWORD, DWORD, DWORD, PSID))
99 GetProcAddress(hAdvApi32, "AllocateAndInitializeSid");
100 pfnEqualSid = (BOOL (__stdcall *)(PSID, PSID))
101 GetProcAddress(hAdvApi32, "EqualSid");
102 pfnFreeSid = (PVOID (__stdcall *)(PSID))
103 GetProcAddress(hAdvApi32, "FreeSid");
105 if (!(pfnOpenThreadToken && pfnOpenProcessToken &&
106 pfnGetTokenInformation && pfnAllocateAndInitializeSid &&
107 pfnEqualSid && pfnFreeSid))
109 warn("Cannot load functions from advapi32.dll library");
110 FreeLibrary(hAdvApi32);
114 if (!pfnOpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hTok)) {
115 if (!pfnOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hTok)) {
116 warn("Cannot open thread token or process token");
117 FreeLibrary(hAdvApi32);
122 pfnGetTokenInformation(hTok, TokenGroups, NULL, 0, &dwTokInfoLen);
123 if (!New(1, lpTokInfo, dwTokInfoLen, TOKEN_GROUPS)) {
124 warn("Cannot allocate token information structure");
126 FreeLibrary(hAdvApi32);
130 if (!pfnGetTokenInformation(hTok, TokenGroups, lpTokInfo, dwTokInfoLen,
133 warn("Cannot get token information");
136 FreeLibrary(hAdvApi32);
140 if (!pfnAllocateAndInitializeSid(&NtAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
141 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid))
143 warn("Cannot allocate administrators' SID");
146 FreeLibrary(hAdvApi32);
151 for (i = 0; i < lpTokInfo->GroupCount; ++i) {
152 if (pfnEqualSid(lpTokInfo->Groups[i].Sid, pAdminSid)) {
158 pfnFreeSid(pAdminSid);
161 FreeLibrary(hAdvApi32);
164 ST(0) = sv_2mortal(newSViv(iRetVal));
168 XS(w32_LookupAccountName)
180 croak("usage: Win32::LookupAccountName($system, $account, $domain, "
181 "$sid, $sidtype);\n");
183 SIDLen = sizeof(SID);
184 DomLen = sizeof(Domain);
187 WCHAR wSID[sizeof(SID)];
188 WCHAR wDomain[sizeof(Domain)];
189 WCHAR wSystem[MAX_PATH+1];
190 WCHAR wAccount[MAX_PATH+1];
191 A2WHELPER(SvPV(ST(0),n_a), wSystem, sizeof(wSystem));
192 A2WHELPER(SvPV(ST(1),n_a), wAccount, sizeof(wAccount));
193 bResult = LookupAccountNameW(wSystem, /* System */
194 wAccount, /* Account name */
195 &wSID, /* SID structure */
196 &SIDLen, /* Size of SID buffer */
197 wDomain, /* Domain buffer */
198 &DomLen, /* Domain buffer size */
199 &snu); /* SID name type */
201 W2AHELPER(wSID, SID, SIDLen);
202 W2AHELPER(wDomain, Domain, DomLen);
206 bResult = LookupAccountNameA(SvPV(ST(0),n_a), /* System */
207 SvPV(ST(1),n_a), /* Account name */
208 &SID, /* SID structure */
209 &SIDLen, /* Size of SID buffer */
210 Domain, /* Domain buffer */
211 &DomLen, /* Domain buffer size */
212 &snu); /* SID name type */
214 sv_setpv(ST(2), Domain);
215 sv_setpvn(ST(3), SID, SIDLen);
216 sv_setiv(ST(4), snu);
223 } /* NTLookupAccountName */
226 XS(w32_LookupAccountSID)
231 DWORD AcctLen = sizeof(Account);
233 DWORD DomLen = sizeof(Domain);
240 croak("usage: Win32::LookupAccountSID($system, $sid, $account, $domain, $sidtype);\n");
242 sid = SvPV(ST(1), n_a);
243 if (IsValidSid(sid)) {
245 WCHAR wSID[sizeof(SID)];
246 WCHAR wDomain[sizeof(Domain)];
247 WCHAR wSystem[MAX_PATH+1];
248 WCHAR wAccount[sizeof(Account)];
249 A2WHELPER(SvPV(ST(0),n_a), wSystem, sizeof(wSystem));
251 bResult = LookupAccountSidW(wSystem, /* System */
252 sid, /* SID structure */
253 wAccount, /* Account name buffer */
254 &AcctLen, /* name buffer length */
255 wDomain, /* Domain buffer */
256 &DomLen, /* Domain buffer length */
257 &snu); /* SID name type */
259 W2AHELPER(wAccount, Account, AcctLen);
260 W2AHELPER(wDomain, Domain, DomLen);
264 bResult = LookupAccountSidA(SvPV(ST(0),n_a), /* System */
265 sid, /* SID structure */
266 Account, /* Account name buffer */
267 &AcctLen, /* name buffer length */
268 Domain, /* Domain buffer */
269 &DomLen, /* Domain buffer length */
270 &snu); /* SID name type */
272 sv_setpv(ST(2), Account);
273 sv_setpv(ST(3), Domain);
274 sv_setiv(ST(4), (IV)snu);
286 } /* NTLookupAccountSID */
288 XS(w32_InitiateSystemShutdown)
291 HANDLE hToken; /* handle to process token */
292 TOKEN_PRIVILEGES tkp; /* pointer to token structure */
294 WCHAR wbuffer[MAX_PATH+1];
295 char *machineName, *message;
299 croak("usage: Win32::InitiateSystemShutdown($machineName, $message, "
300 "$timeOut, $forceClose, $reboot);\n");
302 machineName = SvPV(ST(0), n_a);
304 A2WHELPER(machineName, wbuffer, sizeof(wbuffer));
307 if (OpenProcessToken(GetCurrentProcess(),
308 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
312 LookupPrivilegeValueW(wbuffer,
314 &tkp.Privileges[0].Luid);
316 LookupPrivilegeValueA(machineName,
318 &tkp.Privileges[0].Luid);
320 tkp.PrivilegeCount = 1; /* only setting one */
321 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
323 /* Get shutdown privilege for this process. */
324 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
325 (PTOKEN_PRIVILEGES)NULL, 0);
328 message = SvPV(ST(1), n_a);
331 int length = strlen(message)+1;
332 New(0, pWBuf, length, WCHAR);
333 A2WHELPER(message, pWBuf, length*sizeof(WCHAR));
334 bRet = InitiateSystemShutdownW(wbuffer, pWBuf,
335 SvIV(ST(2)), SvIV(ST(3)), SvIV(ST(4)));
339 bRet = InitiateSystemShutdownA(machineName, message,
340 SvIV(ST(2)), SvIV(ST(3)), SvIV(ST(4)));
342 /* Disable shutdown privilege. */
343 tkp.Privileges[0].Attributes = 0;
344 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
345 (PTOKEN_PRIVILEGES)NULL, 0);
350 XS(w32_AbortSystemShutdown)
353 HANDLE hToken; /* handle to process token */
354 TOKEN_PRIVILEGES tkp; /* pointer to token structure */
358 WCHAR wbuffer[MAX_PATH+1];
361 croak("usage: Win32::AbortSystemShutdown($machineName);\n");
363 machineName = SvPV(ST(0), n_a);
365 A2WHELPER(machineName, wbuffer, sizeof(wbuffer));
368 if (OpenProcessToken(GetCurrentProcess(),
369 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
373 LookupPrivilegeValueW(wbuffer,
375 &tkp.Privileges[0].Luid);
377 LookupPrivilegeValueA(machineName,
379 &tkp.Privileges[0].Luid);
381 tkp.PrivilegeCount = 1; /* only setting one */
382 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
384 /* Get shutdown privilege for this process. */
385 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
386 (PTOKEN_PRIVILEGES)NULL, 0);
390 bRet = AbortSystemShutdownW(wbuffer);
393 bRet = AbortSystemShutdownA(machineName);
395 /* Disable shutdown privilege. */
396 tkp.Privileges[0].Attributes = 0;
397 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
398 (PTOKEN_PRIVILEGES)NULL, 0);
408 char *title = "Perl";
409 DWORD flags = MB_ICONEXCLAMATION;
413 if (items < 1 || items > 3)
414 croak("usage: Win32::MsgBox($message [, $flags [, $title]]);\n");
416 msg = SvPV(ST(0), n_a);
420 title = SvPV(ST(2), n_a);
426 length = strlen(msg)+1;
427 New(0, pMsg, length, WCHAR);
428 A2WHELPER(msg, pMsg, length*sizeof(WCHAR));
429 length = strlen(title)+1;
430 New(0, pTitle, length, WCHAR);
431 A2WHELPER(title, pTitle, length*sizeof(WCHAR));
432 result = MessageBoxW(GetActiveWindow(), pMsg, pTitle, flags);
437 result = MessageBoxA(GetActiveWindow(), msg, title, flags);
450 croak("usage: Win32::LoadLibrary($libname)\n");
451 lpName = (char *)SvPV(ST(0),n_a);
453 WCHAR wbuffer[MAX_PATH+1];
454 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
455 hHandle = LoadLibraryW(wbuffer);
458 hHandle = LoadLibraryA(lpName);
459 XSRETURN_IV((long)hHandle);
466 croak("usage: Win32::FreeLibrary($handle)\n");
467 if (FreeLibrary((HINSTANCE) SvIV(ST(0)))) {
473 XS(w32_GetProcAddress)
478 croak("usage: Win32::GetProcAddress($hinstance, $procname)\n");
479 XSRETURN_IV((long)GetProcAddress((HINSTANCE)SvIV(ST(0)), SvPV(ST(1), n_a)));
482 XS(w32_RegisterServer)
492 croak("usage: Win32::RegisterServer($libname)\n");
494 lpName = SvPV(ST(0),n_a);
496 WCHAR wbuffer[MAX_PATH+1];
497 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
498 hnd = LoadLibraryW(wbuffer);
501 hnd = LoadLibraryA(lpName);
504 func = GetProcAddress(hnd, "DllRegisterServer");
505 if (func && func() == 0)
515 XS(w32_UnregisterServer)
525 croak("usage: Win32::UnregisterServer($libname)\n");
527 lpName = SvPV(ST(0),n_a);
529 WCHAR wbuffer[MAX_PATH+1];
530 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
531 hnd = LoadLibraryW(wbuffer);
534 hnd = LoadLibraryA(lpName);
537 func = GetProcAddress(hnd, "DllUnregisterServer");
538 if (func && func() == 0)
548 /* XXX rather bogus */
552 XSRETURN_PV(getenv("PROCESSOR_ARCHITECTURE"));
560 Zero(&sysinfo,1,SYSTEM_INFO);
561 GetSystemInfo(&sysinfo);
562 /* XXX docs say dwProcessorType is deprecated on NT */
563 XSRETURN_IV(sysinfo.dwProcessorType);
570 char szGUID[50] = {'\0'};
571 HRESULT hr = CoCreateGuid(&guid);
574 LPOLESTR pStr = NULL;
575 if (SUCCEEDED(StringFromCLSID(&guid, &pStr))) {
576 WideCharToMultiByte(CP_ACP, 0, pStr, wcslen(pStr), szGUID,
577 sizeof(szGUID), NULL, NULL);
585 XS(w32_GetFolderPath)
588 char path[MAX_PATH+1];
593 if (items != 1 && items != 2)
594 croak("usage: Win32::GetFolderPath($csidl [, $create])\n");
596 folder = SvIV(ST(0));
598 create = SvTRUE(ST(1)) ? CSIDL_FLAG_CREATE : 0;
600 /* We are not bothering with USING_WIDE() anymore,
601 * because this is not how Unicode works with Perl.
602 * Nobody seems to use "perl -C" anyways.
604 module = LoadLibrary("shfolder.dll");
606 PFNSHGetFolderPath pfn;
607 pfn = (PFNSHGetFolderPath)GetProcAddress(module, "SHGetFolderPathA");
608 if (pfn && SUCCEEDED(pfn(NULL, folder|create, NULL, 0, path))) {
615 module = LoadLibrary("shell32.dll");
617 PFNSHGetSpecialFolderPath pfn;
618 pfn = (PFNSHGetSpecialFolderPath)
619 GetProcAddress(module, "SHGetSpecialFolderPathA");
620 if (pfn && pfn(NULL, path, folder, !!create)) {
629 XS(w32_GetFileVersion)
638 croak("usage: Win32::GetFileVersion($filename)\n");
640 filename = SvPV_nolen(ST(0));
641 size = GetFileVersionInfoSize(filename, &handle);
645 New(0, data, size, char);
649 if (GetFileVersionInfo(filename, handle, size, data)) {
650 VS_FIXEDFILEINFO *info;
652 if (VerQueryValue(data, "\\", (void**)&info, &len)) {
653 int dwValueMS1 = (info->dwFileVersionMS>>16);
654 int dwValueMS2 = (info->dwFileVersionMS&0xffff);
655 int dwValueLS1 = (info->dwFileVersionLS>>16);
656 int dwValueLS2 = (info->dwFileVersionLS&0xffff);
658 if (GIMME_V == G_ARRAY) {
660 XST_mIV(0, dwValueMS1);
661 XST_mIV(1, dwValueMS2);
662 XST_mIV(2, dwValueLS1);
663 XST_mIV(3, dwValueLS2);
668 sprintf(version, "%d.%d.%d.%d", dwValueMS1, dwValueMS2, dwValueLS1, dwValueLS2);
683 char *file = __FILE__;
685 newXS("Win32::LookupAccountName", w32_LookupAccountName, file);
686 newXS("Win32::LookupAccountSID", w32_LookupAccountSID, file);
687 newXS("Win32::InitiateSystemShutdown", w32_InitiateSystemShutdown, file);
688 newXS("Win32::AbortSystemShutdown", w32_AbortSystemShutdown, file);
689 newXS("Win32::ExpandEnvironmentStrings", w32_ExpandEnvironmentStrings, file);
690 newXS("Win32::MsgBox", w32_MsgBox, file);
691 newXS("Win32::LoadLibrary", w32_LoadLibrary, file);
692 newXS("Win32::FreeLibrary", w32_FreeLibrary, file);
693 newXS("Win32::GetProcAddress", w32_GetProcAddress, file);
694 newXS("Win32::RegisterServer", w32_RegisterServer, file);
695 newXS("Win32::UnregisterServer", w32_UnregisterServer, file);
696 newXS("Win32::GetArchName", w32_GetArchName, file);
697 newXS("Win32::GetChipName", w32_GetChipName, file);
698 newXS("Win32::GuidGen", w32_GuidGen, file);
699 newXS("Win32::GetFolderPath", w32_GetFolderPath, file);
700 newXS("Win32::IsAdminUser", w32_IsAdminUser, file);
701 newXS("Win32::GetFileVersion", w32_GetFileVersion, file);