Windows OS Utilities

This library is a collection of assorted functions specific to the Windows operating system. It requires Franz Allegro Common Lisp for Windows, version 6 or greater. Note that this library replaces the single file qrg\code-library\lisp\win-utils.lsp and use of that file is now discouraged. See "Notes on Upgrading from Win-Utils.lsp" for information on upgrading your old code to this new library.


File-System

(wu:file-readonly? path)

Returns non-nil if and only if the specified file has its read-only flag set.

(setf (wu:file-readonly? pathspec) <non-nil | nil >)

Changes the specified file's read-only flag. Note that this function won't change the flag if it's already set to the requested value, thus saving time, since it's faster to check the read-only flag than it is to set it. An error may be signalled if the code is running in a user account that does not have permission to change file attributes.

(wu:make-directory-writable directory-path &key recurse?)

Makes all the files in the directory writable. Returns non-nil on success. If recurse? is non-nil then all subdirectories will be modified as well.

(wu:directory? path)

Returns non-nil if and only if the specified path is a directory.


Miscellaneous Operating System Functionality

(wu:shell-execute filename &key (operation :open) (parameters nil)
                                                     (show-command win:SW_SHOWNORMAL) (default-directory nil))

Alas, Franz's excl:run-shell-command has improved over time but it still can't "run" anything other than executables, whereas the real Windows ShellExecute function, if given a non-executable, will open the file with the executable associated with it. This, of course, is often needed. (For example, to open a Word document or PDF file that contains your application's user-manual.) So, we have wu:shell-execute, which really uses the true Windows ShellExecute command.

This command runs an executable file or acts upon a document using its associated application. The arguments are as follows: Shell-execute returns two values — the first is non-nil iff the execution was considered successful, and the second is the result-code returned from the operating system. A result-code greater than 32 indicates success while the following codes are used to indicate an error:

(wu:describe-OS)

Returns three values: The string is guaranteed to contain no whitespace and so can be used for messages that expect a single word to describe the machine type.

(wu:os-shell-path path-type &rest subdirs)

This function is used for fetching system paths like "My Documents". If specified, it appends the list of sub-directories to the returned system path.

The path-type argument should be one of the Windows CSIDL_* constants. These are described in detail in the Windows SDK documentation, but the constants have been defined in the win-utils package and some common ones are described below:


Utilities for Inspecting Running Processes

(wu:foreground-app-name)

Returns two values: the name of the current process and its process ID.

(wu:window-image-name hwnd)

Returns the name of the process that started this window.

(wu:window-process-id hwnd)

Returns the process ID of the process that started this window.

(wu:list-process-ids)

Returns a list of the IDs of all the processes currently running.

(wu:process-id-name pid)

Returns the name of the process.

(wu:map-process-modules fn pid)

Iterates over the modules active within a given process. For each module, fn will be called with two arguments:
   1) the handle to the process (which is of type HANDLE)
   2) the handle to the module (which is of type HMODULE)
Both of these values are only valid within the scope of the function call, so don't keep them around to use later.

(wu:get-module-info hProcess hModule)

Returns a module-info object describing the specified module.

(wu:module-basename hProcess hModule)

Returns the base name of the specified module.

(wu:module-filename hProcess hModule)

Returns the full path to the specified module's disk file (usually a DLL).

(wu:mappedfile-name hProcess hModule)

Returns the name of a Windows mapped file (these are file streams mapped into memory and sharable between processes).


Utilities for Examining Memory Allocation

(wu:memory-map process-id &key (strict-merge? t))

Returns an ordered list of mem-block objects detailing the virtual memory space as seen by a specified process (via the process ID pid). If strict-merge? is nil, adjeacent memory blocks will be merged together if they are owned by the same module; if non-nil, adjacent blocks will only be merged if they have the same owner, the same sharing permissions, and the same protection attributes. This function can use a lot of memory and can take some time to run. It's not meant to be called often.

(wu:print-memory-map &key (mem-map nil) (strict-merge? t) (str *standard-output*))

Prints a human-readable description of the current process' virtual memory space. Also returns an ordered list of mem-block objects as via a call to memory-map.

(wu:find-optimal-heap-placement &key (str *standard-output*))

Finds the largest contiguous block of RAM that could be used for your Lisp image's heap. This is quite specific to a given machine, so is not so useful when making executables, but is useful if you want to tweak your own Lisp image to gain the maximum possible heap size. This is probably best used in a freshly started Lisp image, but it can be instructive to use it while you are running your application as well, since your app will most likely cause additional DLLs and such to be loaded. Returns two values: a mem-block object representing the recommended space for your Lisp heap and an ordered list of mem-block objects generated as via the memory-map function.

The following shows an example of the output. (This was generated on a machine running WindowsXP Pro with SP1.)

================================================================================
Memory map:
--------------------------------------------------------------------------------

   start      size      prot  owner
--------------------------------------------------------------------------------
00010000      1344K P   0100  < *unused* >
00160000       128K S   0001  \Device\HarddiskVolume3\WINDOWS\SYSTEM32\UNICODE.NLS
00180000       256K S   0001  \Device\HarddiskVolume3\WINDOWS\SYSTEM32\LOCALE.NLS
001c0000       320K S   0001  \Device\HarddiskVolume3\WINDOWS\SYSTEM32\SORTKEY.NLS
00210000        64K S   0001  \Device\HarddiskVolume3\WINDOWS\SYSTEM32\SORTTBLS.NLS
00220000     21760K S   0011  < ??? >
01760000        64K S   0001  \Device\HarddiskVolume3\WINDOWS\SYSTEM32\CTYPE.NLS
01770000      2240K P   0100  < *unused* >
019a0000        64K S   0001  tabhook.dll    (C:\WINDOWS\System32\tabhook.dll)
019b0000       128K P   0100  < *unused* >
019d0000       192K S   0001  msctfime.ime   (C:\WINDOWS\System32\msctfime.ime)
01a00000      1728K S   0100  < ??? >
01bb0000       212K S   0001  \Device\HarddiskVolume3\WINDOWS\Registration\R000000000010.clb
01be5000      1196K P   0100  < *unused* >
01d10000       256K S   0001  ODBC32.dll     (C:\WINDOWS\System32\ODBC32.dll)
01d50000        64K S   0001  odbcbcp.dll    (C:\WINDOWS\System32\odbcbcp.dll)
01d60000    232064K P   0100  < *unused* >
10000000    254272K S   0001  PGPhk.dll      (C:\WINDOWS\system32\PGPhk.dll)
1f850000      5056K S   0001  odbcint.dll    (C:\WINDOWS\System32\odbcint.dll)
1fd40000      4096K P   0100  *** YOUR LISP PLL HERE ***
20140000    773952K P   0100  *** YOUR LISP HEAP HERE ***
4f510000    109504K S   0001  SHELL32.dll    (C:\WINDOWS\system32\SHELL32.dll)
56000000     79296K P   0100  < *unused* >
5ad70000    127296K S   0001  uxtheme.dll    (C:\WINDOWS\System32\uxtheme.dll)
629c0000     14912K S   0001  LPK.DLL        (C:\WINDOWS\System32\LPK.DLL)
63850000    215168K S   0001  acl623.dll     (C:\_apps\acl620\acl623.dll)
70a70000     10816K S   0001  SHLWAPI.dll    (C:\WINDOWS\system32\SHLWAPI.dll)
71500000      2048K S   0001  browseui.dll   (C:\WINDOWS\System32\browseui.dll)
71700000      2368K S   0001  shdocvw.dll    (C:\WINDOWS\System32\shdocvw.dll)
71950000      1344K S   0001  comctl32.dll   (C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.1579_x-ww_7bbf8d08\comctl32.dll)
71aa0000        64K S   0001  WS2HELP.dll    (C:\WINDOWS\system32\WS2HELP.dll)
71ab0000       128K S   0001  WS2_32.dll     (C:\WINDOWS\system32\WS2_32.dll)
71ad0000      1344K S   0001  WSOCK32.dll    (C:\WINDOWS\system32\WSOCK32.dll)
71c20000      9408K S   0001  NETAPI32.dll   (C:\WINDOWS\System32\NETAPI32.dll)
72550000     10560K S   0001  pdh.dll        (C:\WINDOWS\System32\pdh.dll)
72fa0000     23872K S   0001  USP10.dll      (C:\WINDOWS\System32\USP10.dll)
746f0000       192K S   0001  Msimtf.dll     (C:\WINDOWS\System32\Msimtf.dll)
74720000      9216K S   0001  MSCTF.dll      (C:\WINDOWS\System32\MSCTF.dll)
75020000     10560K S   0001  aclre32.dll    (C:\_apps\acl620\cg\aclre32.dll)
75a70000      4928K S   0001  USERENV.dll    (C:\WINDOWS\system32\USERENV.dll)
75f40000      3456K S   0001  appHelp.dll    (C:\WINDOWS\system32\appHelp.dll)
762a0000       128K S   0001  MSASN1.dll     (C:\WINDOWS\system32\MSASN1.dll)
762c0000       832K S   0001  CRYPT32.dll    (C:\WINDOWS\system32\CRYPT32.dll)
76390000       128K S   0001  IMM32.DLL      (C:\WINDOWS\System32\IMM32.DLL)
763b0000      2368K S   0001  comdlg32.dll   (C:\WINDOWS\system32\comdlg32.dll)
76600000       128K S   0001  CSCDLL.dll     (C:\WINDOWS\System32\CSCDLL.dll)
76620000       320K S   0001  cscui.dll      (C:\WINDOWS\System32\cscui.dll)
76670000      3200K S   0001  SETUPAPI.dll   (C:\WINDOWS\System32\SETUPAPI.dll)
76990000      1600K S   0001  ntshrui.dll    (C:\WINDOWS\System32\ntshrui.dll)
76b20000       128K S   0001  ATL.DLL        (C:\WINDOWS\System32\ATL.DLL)
76b40000       704K S   0001  WINMM.dll      (C:\WINDOWS\system32\WINMM.dll)
76bf0000      3712K S   0001  psapi.dll      (C:\WINDOWS\System32\psapi.dll)
76f90000       768K S   0001  Secur32.dll    (C:\WINDOWS\System32\Secur32.dll)
77050000       832K S   0001  COMRes.dll     (C:\WINDOWS\System32\COMRes.dll)
77120000       576K S   0001  OLEAUT32.dll   (C:\WINDOWS\system32\OLEAUT32.dll)
771b0000      1600K S   0001  ole32.dll      (C:\WINDOWS\System32\ole32.dll)
77340000      8960K S   0001  comctl32.dll   (C:\WINDOWS\system32\comctl32.dll)
77c00000        64K S   0001  VERSION.dll    (C:\WINDOWS\system32\VERSION.dll)
77c10000      1216K S   0001  MSVCRT.dll     (C:\WINDOWS\system32\MSVCRT.dll)
77d40000       576K S   0001  USER32.dll     (C:\WINDOWS\system32\USER32.dll)
77dd0000       576K S   0001  ADVAPI32.dll   (C:\WINDOWS\system32\ADVAPI32.dll)
77e60000       960K S   0001  kernel32.dll   (C:\WINDOWS\system32\kernel32.dll)
77f50000       704K S   0001  ntdll.dll      (C:\WINDOWS\System32\ntdll.dll)
78000000     74304K S   0001  RPCRT4.dll     (C:\WINDOWS\system32\RPCRT4.dll)
7c890000     40384K S   0001  CLBCATQ.DLL    (C:\WINDOWS\System32\CLBCATQ.DLL)
7f000000      7104K S   0001  GDI32.dll      (C:\WINDOWS\system32\GDI32.dll)
7f6f0000      9280K S   0011  < ??? >
================================================================================

For maximum size on this machine, your heap should start at 0x20140000.
This will allow it to expand to 755 MB.
The first module preventing further expansion is SHELL32.dll.

================================================================================
  

Notes on Upgrading from Win-Utils.lsp

The file qrg\code-library\list\win-utils.lsp has now been deprecated. It was always awkward to use since it didn't have a normal defsys file for loading and thus forced developers to write special code to ensure it was compiled. Furthermore, over time Franz Allegro has built much of its functionality directly into ACL, thus eliminating the need for us to maintain these functions ourselves. This section describes which functions have been obsoleted and what you should call instead.

load-dll-if-needed

You should now use cl:load (yep, the regular Common Lisp load function) to load your DLLs. It's now smart enough to avoid loading duplicate copies of a DLL and furthermore allows the executable-building functions to know what DLLs your application depends upon. Of special note in this regard is the :system-library keyword argument which is used to tell Allegro that the DLL is a system-wide DLL and should not be included in the executable distribution. (If the DLL is under /windows/system32/, then it is most likely a system-wide DLL and not an application-specific DLL. Including these in your distribution may violate copyrights and furthermore might not even work under a different version of the operating system.)

show-url-in-default-html-browser

Use cg:invoke-html-browser instead. It used to be the case that this function would only work with Internet Explorer and Netscape, but now can use whatever the user has set as their default browser (though it still works faster with IE and Netscape/Mozilla browsers). Furthermore, Franz's function seems more reliable than our function ever was.

shell-execute

This function still exists but note that the arguments have been changed dramatically. The old argument list was cumbersome because almost all uses of this function used the same values for many of the arguments and it was a pain to fill out all the arguments just to get default behavior. Now, most of the arguments are keyword arguments and the default values for these are just fine for most uses.