Add Win32::GetFileVersion() function
Jan Dubois [Wed, 11 May 2005 22:30:37 +0000 (15:30 -0700)]
From: "Jan Dubois" <jand@ActiveState.com>
Message-Id: <200505120530.j4C5UhpX031152@smtp3.ActiveState.com>

p4raw-id: //depot/perl@24453

win32/ext/Win32/Win32.pm
win32/ext/Win32/Win32.xs

index 02e72bc..f3517b1 100644 (file)
@@ -368,6 +368,13 @@ $ENV{PROCESSOR_ARCHITECTURE}.  This might not work on Win9X.
 does not return a UNC path, since the functionality required for such
 a feature is not available under Windows 95.
 
+=item Win32::GetFileVersion(FILENAME)
+
+[EXT] Returns the file version number from the VERSIONINFO resource of
+the executable file or DLL.  This is a tuple of four 16 bit numbers.
+In list context these four numbers will be returned.  In scalar context
+they are concatenated into a string, separated by dots.
+
 =item Win32::GetFolderPath(FOLDER [, CREATE])
 
 [EXT] Returns the full pathname of one of the Windows special folders.
@@ -555,6 +562,19 @@ function.
 system boot.  Resolution is limited to system timer ticks (about 10ms
 on WinNT and 55ms on Win9X).
 
+=item Win32::GuidGen()
+
+[EXT] Creates a globally unique 128 bit integer that can be used as a
+persistent identifier in a distributed setting. To a very high degree
+of certainty this function returns a unique value. No other
+invocation, on the same or any other system (networked or not), should
+return the same value.
+
+The return value is formatted according to OLE conventions, as groups
+of hex digits with surrounding braces.  For example:
+
+    {09531CF1-D0C7-4860-840C-1C8C8735E2AD}
 =item Win32::InitiateSystemShutdown
 
 (MACHINE, MESSAGE, TIMEOUT, FORCECLOSE, REBOOT)
index e15fc81..5342dca 100644 (file)
@@ -572,14 +572,14 @@ XS(w32_GuidGen)
 
     if (SUCCEEDED(hr)) {
        LPOLESTR pStr = NULL;
-       StringFromCLSID(&guid, &pStr);
-       WideCharToMultiByte(CP_ACP, 0, pStr, wcslen(pStr), szGUID,
-                           sizeof(szGUID), NULL, NULL);
-
-       XSRETURN_PV(szGUID);
+       if (SUCCEEDED(StringFromCLSID(&guid, &pStr))) {
+            WideCharToMultiByte(CP_ACP, 0, pStr, wcslen(pStr), szGUID,
+                                sizeof(szGUID), NULL, NULL);
+            CoTaskMemFree(pStr);
+            XSRETURN_PV(szGUID);
+        }
     }
-    else
-       XSRETURN_UNDEF;
+    XSRETURN_UNDEF;
 }
 
 XS(w32_GetFolderPath)
@@ -626,6 +626,57 @@ XS(w32_GetFolderPath)
     XSRETURN_UNDEF;
 }
 
+XS(w32_GetFileVersion)
+{
+    dXSARGS;
+    DWORD size;
+    DWORD handle;
+    char *filename;
+    char *data;
+
+    if (items != 1)
+       croak("usage: Win32::GetFileVersion($filename)\n");
+
+    filename = SvPV_nolen(ST(0));
+    size = GetFileVersionInfoSize(filename, &handle);
+    if (!size)
+        XSRETURN_UNDEF;
+
+    New(0, data, size, char);
+    if (!data)
+        XSRETURN_UNDEF;
+
+    if (GetFileVersionInfo(filename, handle, size, data)) {
+        VS_FIXEDFILEINFO *info;
+        UINT len;
+        if (VerQueryValue(data, "\\", (void**)&info, &len)) {
+            int dwValueMS1 = (info->dwFileVersionMS>>16);
+            int dwValueMS2 = (info->dwFileVersionMS&0xffff);
+            int dwValueLS1 = (info->dwFileVersionLS>>16);
+            int dwValueLS2 = (info->dwFileVersionLS&0xffff);
+
+            if (GIMME_V == G_ARRAY) {
+                EXTEND(SP, 4);
+                XST_mIV(0, dwValueMS1);
+                XST_mIV(1, dwValueMS2);
+                XST_mIV(2, dwValueLS1);
+                XST_mIV(3, dwValueLS2);
+                items = 4;
+            }
+            else {
+                char version[50];
+                sprintf(version, "%d.%d.%d.%d", dwValueMS1, dwValueMS2, dwValueLS1, dwValueLS2);
+                XST_mPV(0, version);
+            }
+        }
+    }
+    else
+        items = 0;
+
+    Safefree(data);
+    XSRETURN(items);
+}
+
 XS(boot_Win32)
 {
     dXSARGS;
@@ -647,6 +698,7 @@ XS(boot_Win32)
     newXS("Win32::GuidGen", w32_GuidGen, file);
     newXS("Win32::GetFolderPath", w32_GetFolderPath, file);
     newXS("Win32::IsAdminUser", w32_IsAdminUser, file);
+    newXS("Win32::GetFileVersion", w32_GetFileVersion, file);
 
     XSRETURN_YES;
 }