WinCC GetAreaPermissionsSQLString Filter Alarm Views by User Area

David Krause10 min read
HMI / SCADASiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

Siemens WinCC Alarm Control (and its PCS 7 successor in the BPC "Basic Process Control" framework) supports per-user filtering of the visible message set through SQL-based dynamic filters. The internal SSM (Security/Session Module) C function SSM::GetAreaPermissionsSQLString builds an SQL WHERE fragment that restricts the alarm query to the plant areas the currently logged-in user is authorized to see, based on the configured Authorization Level in the WinCC User Administrator.

Because this API is not exposed in the WinCC Information System help, projects typically call it through a small C dynamic-link library (DLL) or through a WinCC C-action that writes the resulting string into the DefaultMsgFilterSQL property of the Alarm Control at runtime. This article documents the function signature, its three parameters, the C syntax needed to invoke it, the integration path into DefaultMsgFilterSQL, and the field-proven caveats collected from real PCS 7 / WinCC V7 projects.

Compatibility note: The function is shipped with the WinCC runtime modules ssmrt.dll and alrtapi.dll. It is available in WinCC V7.0 SP3 through WinCC V7.5 SP2 and in PCS 7 V8.0 through V9.0 SP2. TIA Portal WinCC Comfort/Advanced does not expose this API; the techniques below target classic WinCC (V7 / PCS 7) only.

Prerequisites

  1. WinCC V7.x or PCS 7 V8.x/V9.x installed and licensed with the User Administrator component.
  2. A configured user group with non-zero Authorization Level in the WinCC User Administrator (e.g., Level 0 = operator, Level 1 = supervisor, Level 2 = process engineer, Level 3 = administrator).
  3. Plant areas assigned to the group under Authorizations → Area. Each user receives a list of permitted area identifiers in the runtime database.
  4. An Alarm Control instance placed on a WinCC picture, with the property DefaultMsgFilterSQL editable (write-access) from a C action or a global script action.
  5. Microsoft Visual C/C++ build environment matching the WinCC target (Visual Studio 2008 SP1 for V7.0–V7.3, VS2010 for V7.4, VS2013 for V7.5 / PCS 7 V9). Always build a release DLL with the "Multibyte character set" (MBCS) option, not Unicode.

Understanding the SSM Function

The function is declared in the WinCC header ssmapi.h (shipped with the WinCC V7 SDK). Its purpose, taken from the inline header comment, is:

"Returns filter string for currently logged user with all areas with permission (dwLevel)."

In other words, the function inspects the runtime security context, enumerates the area authorizations granted to the active user at the requested level, and serializes them as a SQL WHERE fragment such as:

((Area = 'AREA_01') OR (Area = 'AREA_03') OR (Area = 'AREA_05'))

Returning an empty string means the user has no areas authorized at the requested level; the caller must then decide whether to block the view entirely or to fall back to a no-filter behavior.

Function Signature and Parameters

The full prototype as exported by ssmrt.dll is:

BOOL SSM::GetAreaPermissionsSQLString(
    DWORD  dwLevel,
    LPTSTR lptAreaSQLString,
    LPDWORD pdwStringLen
);
Parameter Direction Type Meaning
dwLevel in DWORD The authorization level (0..N) whose area list is requested. Corresponds to the level configured in the WinCC User Administrator under the group's "Authorization" column.
lptAreaSQLString out LPTSTR (pointer to TCHAR buffer) Caller-allocated buffer that receives the SQL filter fragment. On entry it is ignored; on return it is filled with a NUL-terminated string.
pdwStringLen in/out LPDWORD (pointer to DWORD) On entry: the buffer size in characters (not bytes). On return: the number of characters written, including the terminating NUL. The WinCC header comment refers to this as "the length of the array".

Return value: TRUE on success, FALSE on failure. The function does not extend Win32 error codes; on failure, inspect the buffer length returned – if it equals the input length, the buffer was too small and the function did not write a complete filter.

Step-by-Step Implementation

  1. Determine the maximum buffer size. A safe upper bound is 16 KB TCHARs (16384). For projects with hundreds of areas you can raise this to 32 KB. sizeof(buffer) / sizeof(TCHAR) is the value to pass.
  2. Call the function once to size, once to fill. Pass a small buffer first; if *pdwStringLen equals the buffer capacity, retry with a larger buffer. The WinCC convention is single-pass: many projects skip the two-call idiom and simply allocate the maximum.
  3. Read the active user. Use SSM::GetCurrentUser() or evaluate the system tag @CurrentUser to log who triggered the filter rebuild.
  4. Wrap the SQL fragment in the Alarm Control syntax. DefaultMsgFilterSQL expects a complete boolean expression, not a partial clause. Prefix the result with the column name(s) of the message archive that hold the area identifier. In a standard PCS 7 BPC project the column is Area in the ARCHIVE message table.
  5. Apply the result to the Alarm Control. Set the property DefaultMsgFilterSQL on the Alarm Control object at picture-open time and on every user change.

C Syntax Example

The following WinCC C action is placed on the Open Picture event of the picture that contains the Alarm Control. It builds the filter and assigns it to the control's DefaultMsgFilterSQL property.

#include "apdefap.h"
#include "ssmapi.h"

#define MAX_FILTER_CHARS 16384

void OnOpenPicture(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName)
{
    TCHAR  szFilter[MAX_FILTER_CHARS];
    DWORD  dwLen   = MAX_FILTER_CHARS;
    DWORD  dwLevel = 2;  /* 0=op, 1=sup, 2=process eng, 3=admin */
    BOOL   bRet;
    CMN_ERROR  Err;

    memset(szFilter, 0, sizeof(szFilter));
    bRet = SSM::GetAreaPermissionsSQLString(dwLevel, szFilter, &dwLen);

    if (bRet == FALSE)
    {
        /* No areas at this level - deny view by returning an impossible match */
        SetPropChar(lpszPictureName, lpszObjectName, "DefaultMsgFilterSQL",
                    "(1 = 0)");
        return;
    }

    if (dwLen == 0)
    {
        /* Empty string - same handling as failure */
        SetPropChar(lpszPictureName, lpszObjectName, "DefaultMsgFilterSQL",
                    "(1 = 0)");
        return;
    }

    /* szFilter already contains the bracketed OR list, e.g.
       ((Area = 'AREA_01') OR (Area = 'AREA_03'))
       so assign it directly. */
    SetPropChar(lpszPictureName, lpszObjectName, "DefaultMsgFilterSQL",
                (LPSTR)szFilter);

    /* Force a refresh of the Alarm Control so the new filter takes effect */
    SetPropBOOL(lpszPictureName, lpszObjectName, "ApplyFilter", TRUE);
}

For users with broad rights, a typical value of szFilter is:

((Area = 'PLANT_A') OR (Area = 'PLANT_B') OR (Area = 'UTILITY'))

Wiring it to DefaultMsgFilterSQL

The DefaultMsgFilterSQL property is the canonical WinCC Alarm Control entry point for dynamic SQL-based message filtering. Property assignments performed from C actions via SetPropChar() are evaluated by the control during the next filter pass. Two field-proven rules apply:

  • Always toggle the ApplyFilter boolean after writing DefaultMsgFilterSQL. Without the toggle the control may keep the previously cached filter, particularly after user changes handled by a hot-key change-picture event.
  • If the alarm archive stores the area identifier in a column other than Area (custom message classes use MsgClassArea or UserArea in some PCS 7 templates), rewrite the prefix in a small wrapper. The SSM function returns the OR-list only; the column name is the caller's responsibility.

Authorization Levels Reference

Level (dwLevel) Typical role in PCS 7 Recommended action on empty result
0 Field operator Show only own unit ((1=0) not used - fall back to "no filter")
1 Shift supervisor Deny access; write a banner message
2 Process engineer Deny access
3 Plant administrator Allow full access ((1=1))
4+ Custom (project-specific) Project policy
Caution: The function reads the active runtime authorization of the logged-in user, not the picture-time user. If the script runs once at picture open, it captures the user who opened the picture. Re-run the call on every user-change event (tag @CurrentUserName) to keep the filter current after a re-login on the same station.

Troubleshooting Matrix

Symptom Likely cause Resolution
Filter returns empty string for every user SSM runtime not loaded; ssmrt.dll missing from bin Reinstall WinCC Runtime; check LoadRetCode in CCLogsConnect.log
Function returns FALSE and buffer untouched dwLevel not configured for the group; no level assigned Open User Administrator → Authorizations → set at least one area per level
Alarm Control shows no rows after filter applied Column name mismatch: archive uses UserArea not Area Inspect MSG_ARCHIVE_CONFIG in SQL; rewrite the prefix in the wrapper
Filter applied at open but ignored after operator re-login Picture-open event fires only once Trigger the C action from a tag-triggered event bound to @CurrentUserName change
SQL syntax error logged in WinCC diagnostics Area names contain single quotes (e.g., PLANT/A) Sanitize area names in the User Administrator: use only A–Z, 0–9, underscore
Unicode build crashes with access violation WinCC is MBCS; DLL compiled as Unicode Rebuild the action DLL with the Multibyte character set
Unresolved external symbol SSM::GetAreaPermissionsSQLString Linker not given the ssmrt.lib import library Add $(WinCCInstallDir)\lib\ssmrt.lib to linker inputs

Related Functions and Alternatives

Function Module Purpose
SSM::GetCurrentUser() ssmrt.dll Returns the name of the currently logged-in user as a TCHAR string
SSM::GetUserLevel() ssmrt.dll Returns the maximum authorization level assigned to the active user
SSM::GetUserName() ssmrt.dll Returns the configured full name of the active user
MSRTGetMsgFilterSQL() alrtapi.dll Builds an SQL filter from message priority and class; can be combined with the area filter
DMGetVariable() on tag @CurrentUserName WinCC tag API Lightweight alternative to SSM::GetCurrentUser for VBS scripts

For projects that cannot call the C API directly, a viable workaround is to read the per-user area list from the WinCC configuration database table dbo.UAM_AREA (PCS 7 V8+) and assemble the SQL fragment in VBS. This is significantly slower but avoids the C toolchain.

Version Compatibility

WinCC version Function available? Notes
V7.0 SP0–SP2 No API introduced in V7.0 SP3
V7.0 SP3 / SP4 Yes Header in ssmapi.h; build with VS2008
V7.2 / V7.3 Yes Same signature
V7.4 Yes Build with VS2010
V7.5 / V7.5 SP2 Yes Build with VS2013; header location WinCC\ApLib\include
PCS 7 V8.0 / V8.1 / V8.2 Yes Wrapper available in BPC template project
PCS 7 V9.0 / V9.0 SP2 Yes Behavior unchanged; column name remains Area
TIA Portal WinCC Comfort/Advanced No API not exposed; use User-Defined Authorizations in the TIA portal instead

Verification

  1. Open the WinCC Graphics Designer, place the Alarm Control, and attach the C action above to the Open Picture event.
  2. Start WinCC Runtime and log in as a user belonging to a group with authorization level 2 and areas PLANT_A, PLANT_B.
  3. Use the WinCC Channel Diagnosis tool CCChannelDiag.exe and the message archive trace CCMsgArchTrace to confirm the runtime query is SELECT ... WHERE ((Area = 'PLANT_A') OR (Area = 'PLANT_B')).
  4. Open User Administrator → Tools → Authorization Check and verify the user entry shows the expected level and area list. Mismatch here is the most common root cause of empty filter results.
  5. Trigger a re-login (log out / log in as a different operator) and confirm the filter refreshes on the picture; if not, bind the action to @CurrentUserName as a trigger tag.
  6. Open the Alarm Control on a second monitor and trigger an alarm in PLANT_A; the alarm must appear. Trigger one in PLANT_C (not authorized) and confirm it does not.

FAQ

What does the SSM::GetAreaPermissionsSQLString function do exactly?

It returns a SQL WHERE-clause fragment that lists all plant areas the currently logged-in WinCC user is authorized to see at a given authorization level (parameter dwLevel). You can then assign that fragment to the Alarm Control property DefaultMsgFilterSQL to restrict the visible messages to those areas.

What are the three parameters of SSM::GetAreaPermissionsSQLString?

The signature is BOOL SSM::GetAreaPermissionsSQLString(DWORD dwLevel, LPTSTR lptAreaSQLString, LPDWORD pdwStringLen). dwLevel is the requested authorization level, lptAreaSQLString is the caller-allocated output buffer that receives the NUL-terminated SQL fragment, and pdwStringLen is a pointer to a DWORD that holds the buffer length on entry and the number of characters written on return.

How do I assign the result to an Alarm Control filter?

Call SetPropChar(lpszPictureName, lpszObjectName, "DefaultMsgFilterSQL", szFilter) from a WinCC C action on the picture-open event, and then set ApplyFilter = TRUE to force a refresh. The function returns the bracketed OR list, for example ((Area = 'PLANT_A') OR (Area = 'PLANT_B')), which is exactly the syntax DefaultMsgFilterSQL expects.

Why does the function return an empty string for my user?

An empty return usually means the user has no area authorizations at the requested dwLevel. Open the WinCC User Administrator, select the user's group, and verify that at least one entry exists under Authorizations → Area for the level you are passing. Confirm that the runtime user database has been reloaded (the User Administrator hot-key F5 reloads it on the active station).

Does this work in TIA Portal WinCC Professional?

No. SSM::GetAreaPermissionsSQLString is an undocumented WinCC V7 / PCS 7 C API. TIA Portal WinCC Professional does not export the SSM module; instead use the built-in User-Defined Authorizations combined with the alarm control property User authorization for area selection, which is the platform-supported equivalent for the same requirement.

Back to blog