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);
239 croak("usage: Win32::LookupAccountSID($system, $sid, $account, $domain, $sidtype);\n");
241 sid = SvPV(ST(1), n_a);
242 if (IsValidSid(sid)) {
244 WCHAR wDomain[sizeof(Domain)];
245 WCHAR wSystem[MAX_PATH+1];
246 WCHAR wAccount[sizeof(Account)];
247 A2WHELPER(SvPV(ST(0),n_a), wSystem, sizeof(wSystem));
249 bResult = LookupAccountSidW(wSystem, /* System */
250 sid, /* SID structure */
251 wAccount, /* Account name buffer */
252 &AcctLen, /* name buffer length */
253 wDomain, /* Domain buffer */
254 &DomLen, /* Domain buffer length */
255 &snu); /* SID name type */
257 W2AHELPER(wAccount, Account, AcctLen);
258 W2AHELPER(wDomain, Domain, DomLen);
262 bResult = LookupAccountSidA(SvPV(ST(0),n_a), /* System */
263 sid, /* SID structure */
264 Account, /* Account name buffer */
265 &AcctLen, /* name buffer length */
266 Domain, /* Domain buffer */
267 &DomLen, /* Domain buffer length */
268 &snu); /* SID name type */
270 sv_setpv(ST(2), Account);
271 sv_setpv(ST(3), Domain);
272 sv_setiv(ST(4), (IV)snu);
284 } /* NTLookupAccountSID */
286 XS(w32_InitiateSystemShutdown)
289 HANDLE hToken; /* handle to process token */
290 TOKEN_PRIVILEGES tkp; /* pointer to token structure */
292 WCHAR wbuffer[MAX_PATH+1];
293 char *machineName, *message;
297 croak("usage: Win32::InitiateSystemShutdown($machineName, $message, "
298 "$timeOut, $forceClose, $reboot);\n");
300 machineName = SvPV(ST(0), n_a);
302 A2WHELPER(machineName, wbuffer, sizeof(wbuffer));
305 if (OpenProcessToken(GetCurrentProcess(),
306 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
310 LookupPrivilegeValueW(wbuffer,
312 &tkp.Privileges[0].Luid);
314 LookupPrivilegeValueA(machineName,
316 &tkp.Privileges[0].Luid);
318 tkp.PrivilegeCount = 1; /* only setting one */
319 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
321 /* Get shutdown privilege for this process. */
322 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
323 (PTOKEN_PRIVILEGES)NULL, 0);
326 message = SvPV(ST(1), n_a);
329 int length = strlen(message)+1;
330 New(0, pWBuf, length, WCHAR);
331 A2WHELPER(message, pWBuf, length*sizeof(WCHAR));
332 bRet = InitiateSystemShutdownW(wbuffer, pWBuf,
333 SvIV(ST(2)), SvIV(ST(3)), SvIV(ST(4)));
337 bRet = InitiateSystemShutdownA(machineName, message,
338 SvIV(ST(2)), SvIV(ST(3)), SvIV(ST(4)));
340 /* Disable shutdown privilege. */
341 tkp.Privileges[0].Attributes = 0;
342 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
343 (PTOKEN_PRIVILEGES)NULL, 0);
348 XS(w32_AbortSystemShutdown)
351 HANDLE hToken; /* handle to process token */
352 TOKEN_PRIVILEGES tkp; /* pointer to token structure */
356 WCHAR wbuffer[MAX_PATH+1];
359 croak("usage: Win32::AbortSystemShutdown($machineName);\n");
361 machineName = SvPV(ST(0), n_a);
363 A2WHELPER(machineName, wbuffer, sizeof(wbuffer));
366 if (OpenProcessToken(GetCurrentProcess(),
367 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
371 LookupPrivilegeValueW(wbuffer,
373 &tkp.Privileges[0].Luid);
375 LookupPrivilegeValueA(machineName,
377 &tkp.Privileges[0].Luid);
379 tkp.PrivilegeCount = 1; /* only setting one */
380 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
382 /* Get shutdown privilege for this process. */
383 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
384 (PTOKEN_PRIVILEGES)NULL, 0);
388 bRet = AbortSystemShutdownW(wbuffer);
391 bRet = AbortSystemShutdownA(machineName);
393 /* Disable shutdown privilege. */
394 tkp.Privileges[0].Attributes = 0;
395 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
396 (PTOKEN_PRIVILEGES)NULL, 0);
406 char *title = "Perl";
407 DWORD flags = MB_ICONEXCLAMATION;
411 if (items < 1 || items > 3)
412 croak("usage: Win32::MsgBox($message [, $flags [, $title]]);\n");
414 msg = SvPV(ST(0), n_a);
418 title = SvPV(ST(2), n_a);
424 length = strlen(msg)+1;
425 New(0, pMsg, length, WCHAR);
426 A2WHELPER(msg, pMsg, length*sizeof(WCHAR));
427 length = strlen(title)+1;
428 New(0, pTitle, length, WCHAR);
429 A2WHELPER(title, pTitle, length*sizeof(WCHAR));
430 result = MessageBoxW(GetActiveWindow(), pMsg, pTitle, flags);
435 result = MessageBoxA(GetActiveWindow(), msg, title, flags);
448 croak("usage: Win32::LoadLibrary($libname)\n");
449 lpName = (char *)SvPV(ST(0),n_a);
451 WCHAR wbuffer[MAX_PATH+1];
452 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
453 hHandle = LoadLibraryW(wbuffer);
456 hHandle = LoadLibraryA(lpName);
457 XSRETURN_IV((long)hHandle);
464 croak("usage: Win32::FreeLibrary($handle)\n");
465 if (FreeLibrary((HINSTANCE) SvIV(ST(0)))) {
471 XS(w32_GetProcAddress)
476 croak("usage: Win32::GetProcAddress($hinstance, $procname)\n");
477 XSRETURN_IV((long)GetProcAddress((HINSTANCE)SvIV(ST(0)), SvPV(ST(1), n_a)));
480 XS(w32_RegisterServer)
490 croak("usage: Win32::RegisterServer($libname)\n");
492 lpName = SvPV(ST(0),n_a);
494 WCHAR wbuffer[MAX_PATH+1];
495 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
496 hnd = LoadLibraryW(wbuffer);
499 hnd = LoadLibraryA(lpName);
502 func = GetProcAddress(hnd, "DllRegisterServer");
503 if (func && func() == 0)
513 XS(w32_UnregisterServer)
523 croak("usage: Win32::UnregisterServer($libname)\n");
525 lpName = SvPV(ST(0),n_a);
527 WCHAR wbuffer[MAX_PATH+1];
528 A2WHELPER(lpName, wbuffer, sizeof(wbuffer));
529 hnd = LoadLibraryW(wbuffer);
532 hnd = LoadLibraryA(lpName);
535 func = GetProcAddress(hnd, "DllUnregisterServer");
536 if (func && func() == 0)
546 /* XXX rather bogus */
550 XSRETURN_PV(getenv("PROCESSOR_ARCHITECTURE"));
558 Zero(&sysinfo,1,SYSTEM_INFO);
559 GetSystemInfo(&sysinfo);
560 /* XXX docs say dwProcessorType is deprecated on NT */
561 XSRETURN_IV(sysinfo.dwProcessorType);
568 char szGUID[50] = {'\0'};
569 HRESULT hr = CoCreateGuid(&guid);
572 LPOLESTR pStr = NULL;
573 if (SUCCEEDED(StringFromCLSID(&guid, &pStr))) {
574 WideCharToMultiByte(CP_ACP, 0, pStr, wcslen(pStr), szGUID,
575 sizeof(szGUID), NULL, NULL);
583 XS(w32_GetFolderPath)
586 char path[MAX_PATH+1];
591 if (items != 1 && items != 2)
592 croak("usage: Win32::GetFolderPath($csidl [, $create])\n");
594 folder = SvIV(ST(0));
596 create = SvTRUE(ST(1)) ? CSIDL_FLAG_CREATE : 0;
598 /* We are not bothering with USING_WIDE() anymore,
599 * because this is not how Unicode works with Perl.
600 * Nobody seems to use "perl -C" anyways.
602 module = LoadLibrary("shfolder.dll");
604 PFNSHGetFolderPath pfn;
605 pfn = (PFNSHGetFolderPath)GetProcAddress(module, "SHGetFolderPathA");
606 if (pfn && SUCCEEDED(pfn(NULL, folder|create, NULL, 0, path))) {
613 module = LoadLibrary("shell32.dll");
615 PFNSHGetSpecialFolderPath pfn;
616 pfn = (PFNSHGetSpecialFolderPath)
617 GetProcAddress(module, "SHGetSpecialFolderPathA");
618 if (pfn && pfn(NULL, path, folder, !!create)) {
627 XS(w32_GetFileVersion)
636 croak("usage: Win32::GetFileVersion($filename)\n");
638 filename = SvPV_nolen(ST(0));
639 size = GetFileVersionInfoSize(filename, &handle);
643 New(0, data, size, char);
647 if (GetFileVersionInfo(filename, handle, size, data)) {
648 VS_FIXEDFILEINFO *info;
650 if (VerQueryValue(data, "\\", (void**)&info, &len)) {
651 int dwValueMS1 = (info->dwFileVersionMS>>16);
652 int dwValueMS2 = (info->dwFileVersionMS&0xffff);
653 int dwValueLS1 = (info->dwFileVersionLS>>16);
654 int dwValueLS2 = (info->dwFileVersionLS&0xffff);
656 if (GIMME_V == G_ARRAY) {
658 XST_mIV(0, dwValueMS1);
659 XST_mIV(1, dwValueMS2);
660 XST_mIV(2, dwValueLS1);
661 XST_mIV(3, dwValueLS2);
666 sprintf(version, "%d.%d.%d.%d", dwValueMS1, dwValueMS2, dwValueLS1, dwValueLS2);
681 char *file = __FILE__;
683 newXS("Win32::LookupAccountName", w32_LookupAccountName, file);
684 newXS("Win32::LookupAccountSID", w32_LookupAccountSID, file);
685 newXS("Win32::InitiateSystemShutdown", w32_InitiateSystemShutdown, file);
686 newXS("Win32::AbortSystemShutdown", w32_AbortSystemShutdown, file);
687 newXS("Win32::ExpandEnvironmentStrings", w32_ExpandEnvironmentStrings, file);
688 newXS("Win32::MsgBox", w32_MsgBox, file);
689 newXS("Win32::LoadLibrary", w32_LoadLibrary, file);
690 newXS("Win32::FreeLibrary", w32_FreeLibrary, file);
691 newXS("Win32::GetProcAddress", w32_GetProcAddress, file);
692 newXS("Win32::RegisterServer", w32_RegisterServer, file);
693 newXS("Win32::UnregisterServer", w32_UnregisterServer, file);
694 newXS("Win32::GetArchName", w32_GetArchName, file);
695 newXS("Win32::GetChipName", w32_GetChipName, file);
696 newXS("Win32::GuidGen", w32_GuidGen, file);
697 newXS("Win32::GetFolderPath", w32_GetFolderPath, file);
698 newXS("Win32::IsAdminUser", w32_IsAdminUser, file);
699 newXS("Win32::GetFileVersion", w32_GetFileVersion, file);