' ########################################################################################
' Microsoft Windows
' File: pstore.inc
' Contents: Protected Storage COM interface and associated data structures.
' Copyright (c) 2011 Jos? Roca
' Portions Copyright (c) Microsoft Corporation.
' All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#IF NOT %DEF(PBX_pstore_PBI)
#DEFINE PBX_pstore_PBI
%EQUATE `PSTORE_INC = 1
'/*
' Typedefs, values
'*/
'// provider flags
'// provider capabilities
'typedef DWORD PST_PROVIDERCAPABILITIES;
%EQUATE `PST_PC_PFX = &H00000001
%EQUATE `PST_PC_HARDWARE = &H00000002
%EQUATE `PST_PC_SMARTCARD = &H00000004
%EQUATE `PST_PC_PCMCIA = &H00000008
%EQUATE `PST_PC_MULTIPLE_REPOSITORIES = &H00000010
%EQUATE `PST_PC_ROAMABLE = &H00000020
'// NYI (not yet implemented)
'typedef DWORD PST_REPOSITORYCAPABILITIES;
%EQUATE `PST_RC_REMOVABLE = &H80000000
'// provider storage area
'typedef DWORD PST_KEY;
%EQUATE `PST_KEY_CURRENT_USER = &H00000000
%EQUATE `PST_KEY_LOCAL_MACHINE = &H00000001
'/*
' dwDefaultConfirmationStyle flags
'*/
'//
'// allows user to choose confirmation style
'//
%EQUATE `PST_CF_DEFAULT = &H00000000
'//
'// forces silent item creation
'//
%EQUATE `PST_CF_NONE = &H00000001
'/*
' dwPromptFlags
'*/
'//
'// app forces confirmation to be shown
'//
%EQUATE `PST_PF_ALWAYS_SHOW = &H00000001
'//
'// RSABase rqmt: determine if item has ui attached
'//
%EQUATE `PST_PF_NEVER_SHOW = &H00000002
'/*
' dwFlags values
'*/
'//
'// Allows caller to specify creation not overwrite
'// of item during WriteItem call
'//
%EQUATE `PST_NO_OVERWRITE = &H00000002
'//
'// specifies insecure data stream to be written/read
'// there is no protection or guarantees for this data
'// flag only valid during item read/write calls
'// default: item calls are secure
'//
%EQUATE `PST_UNRESTRICTED_ITEMDATA = &H00000004
'//
'// on ReadItem call
'// return value on success without UI on item is PST_E_OK
'// return value on success with UI on item is PST_E_ITEM_EXISTS
'// return value on failure is a different error code
'//
%EQUATE `PST_PROMPT_QUERY = &H00000008
'//
'// on ReadItem, DeleteItem, for data migration purposes:
'// Avoid displaying UI on ReadItem unless a custom password is required (highsecurity).
'// Avoid displaying UI on DeleteItem, period.
'//
%EQUATE `PST_NO_UI_MIGRATION = &H00000010
'/*
' Security masks, rule modifiers
'*/
'//
'// models access after NT access mask
'//
'// read, write
'typedef DWORD PST_ACCESSMODE;
%EQUATE `PST_READ = &H0001
%EQUATE `PST_WRITE = &H0002
'// PST_ACCESSCLAUSETYPE
'// memhash, diskhash, authenticode, etc
'typedef DWORD PST_ACCESSCLAUSETYPE;
'//
'// pbClauseData points to PST_AUTHENTICODEDATA structure.
'//
%EQUATE `PST_AUTHENTICODE = 1
'//
'// pbClauseData points to PST_BINARYCHECKDATA structure.
'//
%EQUATE `PST_BINARY_CHECK = 2
'//
'// pbClauseData points to valid Windows NT security descriptor.
'// note that performance is improved on Set operations if the security
'// descriptor is in self-relative format, with valid owner and group Sids
'// (non-NULL).
'//
%EQUATE `PST_SECURITY_DESCRIPTOR = 4
'//
'// pbClauseData is in self-relative format
'// (for internal use only)
'//
%EQUATE `PST_SELF_RELATIVE_CLAUSE = &H80000000
'//
'// currently access clause modifiers - NOT to be or'd together
'//
'//
'// specified image is the immediate caller, and is an application (.exe)
'//
%EQUATE `PST_AC_SINGLE_CALLER = 0
'//
'// specified image is not necessary the immediate caller, and is an
'// application (.exe)
'//
%EQUATE `PST_AC_TOP_LEVEL_CALLER = 1
'//
'// specified image is the immediate caller. May be
'// an application (.exe) or a .dll
'//
%EQUATE `PST_AC_IMMEDIATE_CALLER = 2
'/*
' Provider Parameters
'*/
'//
'// flush the internal cache of passwords -- temporary?
'//
%EQUATE `PST_PP_FLUSH_PW_CACHE = &H1
'/*
' Provider Defns
'*/
'//
'// Microsoft Base Provider (MS_BASE_PSTPROVIDER...)
'//
$$MS_BASE_PSTPROVIDER_NAME = "System Protected Storage"$$
'// {8A078C30-3755-11d0-A0BD-00AA0061426A}
$MS_BASE_PSTPROVIDER_ID = GUID$("{8A078C30-3755-11d0-A0BD-00AA0061426A}")
$$MS_BASE_PSTPROVIDER_SZID = "8A078C30-3755-11d0-A0BD-00AA0061426A"$$
'//
'// Microsoft PFX Provider (MS_PFX_PSTPROVIDER...)
'//
$$MS_PFX_PSTPROVIDER_NAME = "PFX Storage Provider"$$
'// {3ca94f30-7ac1-11d0-8c42-00c04fc299eb}
$MS_PFX_PSTPROVIDER_ID = GUID$("{3ca94f30-7ac1-11d0-8c42-00c04fc299eb}")
$$MS_PFX_PSTPROVIDER_SZID = "3ca94f30-7ac1-11d0-8c42-00c04fc299eb"$$
'/*
' Globally registered Type/Subtype guid/name pairs
'*/
$$PST_CONFIGDATA_TYPE_STRING = "Configuration Data"$$
'// 8ec99652-8909-11d0-8c4d-00c04fc297eb
$PST_CONFIGDATA_TYPE_GUID = GUID$("{8ec99652-8909-11d0-8c4d-00c04fc297eb}")
$$PST_PROTECTEDSTORAGE_SUBTYPE_STRING = "Protected Storage"$$
'// d3121b8e-8a7d-11d0-8c4f-00c04fc297eb
$PST_PROTECTEDSTORAGE_SUBTYPE_GUID = GUID$("{d3121b8e-8a7d-11d0-8c4f-00c04fc297eb}")
$$PST_PSTORE_PROVIDERS_SUBTYPE_STRING = "Protected Storage Provider List"$$
'// 8ed17a64-91d0-11d0-8c43-00c04fc2c621
$PST_PSTORE_PROVIDERS_SUBTYPE_GUID = GUID$("{8ed17a64-91d0-11d0-8c43-00c04fc2c621}")
'//
'// error codes
'//
#IF NOT %DEF(%PST_E_OK)
%EQUATE `PST_E_OK = &H00000000&
%EQUATE `PST_E_FAIL = &H800C0001&
%EQUATE `PST_E_PROV_DLL_NOT_FOUND = &H800C0002&
%EQUATE `PST_E_INVALID_HANDLE = &H800C0003&
%EQUATE `PST_E_TYPE_EXISTS = &H800C0004&
%EQUATE `PST_E_TYPE_NO_EXISTS = &H800C0005&
%EQUATE `PST_E_INVALID_RULESET = &H800C0006&
%EQUATE `PST_E_NO_PERMISSIONS = &H800C0007&
%EQUATE `PST_E_STORAGE_ERROR = &H800C0008&
%EQUATE `PST_E_CALLER_NOT_VERIFIED = &H800C0009&
%EQUATE `PST_E_WRONG_PASSWORD = &H800C000A&
%EQUATE `PST_E_DISK_IMAGE_MISMATCH = &H800C000B&
'// 000C pending
%EQUATE `PST_E_UNKNOWN_EXCEPTION = &H800C000D&
%EQUATE `PST_E_BAD_FLAGS = &H800C000E&
%EQUATE `PST_E_ITEM_EXISTS = &H800C000F&
%EQUATE `PST_E_ITEM_NO_EXISTS = &H800C0010&
%EQUATE `PST_E_SERVICE_UNAVAILABLE = &H800C0011&
%EQUATE `PST_E_NOTEMPTY = &H800C0012&
%EQUATE `PST_E_INVALID_STRING = &H800C0013&
%EQUATE `PST_E_STATE_INVALID = &H800C0014&
%EQUATE `PST_E_NOT_OPEN = &H800C0015&
%EQUATE `PST_E_ALREADY_OPEN = &H800C0016&
%EQUATE `PST_E_NYI = &H800C0F00&
%EQUATE `MIN_PST_ERROR = &H800C0001&
%EQUATE `MAX_PST_ERROR = &H800C0F00&
#ENDIF ' // !PST_OK
' /* header files for imported files */
#INCLUDE ONCE "Legacy/System/WTypes.inc"
'/****************************************
' * Generated header for interface: __MIDL__intf_0000
' * at Wed Apr 23 23:56:10 1997
' * using MIDL 3.00.44
' ****************************************/
'typedef DWORD PST_PROVIDERCAPABILITIES;
'typedef DWORD PST_REPOSITORYCAPABILITIES;
'typedef DWORD PST_KEY;
'typedef DWORD PST_ACCESSMODE;
'typedef DWORD PST_ACCESSCLAUSETYPE;
'typedef GUID UUID;
'typedef ULARGE_INTEGER PST_PROVIDER_HANDLE;
'typedef GUID PST_PROVIDERID;
'typedef PST_PROVIDERID __RPC_FAR *PPST_PROVIDERID;
' // Size = 28 bytes
TYPE PST_PROVIDERINFO DWORD
 cbSize AS DWORD
 ID AS GUID ' PST_PROVIDERID
 Capabilities AS DWORD ' PST_PROVIDERCAPABILITIES
 szProviderName AS WSTRINGZ PTR
END TYPE
' // Size = 8 bytes
TYPE PST_TYPEINFO DWORD
 cbSize AS DWORD
 szDisplayName AS WSTRINGZ PTR
END TYPE
' // Size = 16 bytes
TYPE PST_PROMPTINFO DWORD
 cbSize AS DWORD
 dwPromptFlags AS DWORD
 hwndApp AS DWORD
 szPrompt AS WSTRINGZ PTR
END TYPE
' // Size = 16 bytes
TYPE PST_ACCESSCLAUSE DWORD
 cbSize AS DWORD
 ClauseType AS DWORD ' PST_ACCESSCLAUSETYPE
 cbClauseData AS DWORD
 pbClauseData AS DWORD ' /* [size_is] */ VOID __RPC_FAR *
END TYPE
' // Size = 16 bytes
TYPE PST_ACCESSRULE DWORD
 cbSize AS DWORD
 AccessModeFlags AS DWORD ' PST_ACCESSMODE
 cClauses AS DWORD
 rgClauses AS DWORD ' /* [size_is] */ PST_ACCESSCLAUSE __RPC_FAR *
END TYPE
' // Size = 12 bytes
TYPE PST_ACCESSRULESET DWORD
 cbSize AS DWORD
 cRules AS DWORD
 rgRules AS DWORD ' /* [size_is] */ PST_ACCESSRULE __RPC_FAR *
END TYPE
' // Size = 24 bytes
TYPE PST_AUTHENTICODEDATA DWORD
 cbSize AS DWORD
 dwModifiers AS DWORD
 szRootCA AS WSTRINGZ PTR
 szIssuer AS WSTRINGZ PTR
 szPublisher AS WSTRINGZ PTR
 szProgramName AS WSTRINGZ PTR
END TYPE
' // Size = 12 bytes
TYPE PST_BINARYCHECKDATA DWORD
 cbSize AS DWORD
 dwModifiers AS DWORD
 szFilePath AS WSTRINGZ PTR
END TYPE
' /* header files for imported files */
#INCLUDE ONCE "Legacy/COM/OAIdl.inc"
#IF NOT %DEF(%PSTORECLib_LIBRARY_DEFINED)
 %PSTORECLib_LIBRARY_DEFINED = 1
$LIBID_PSTORECLib = GUID$("{5A6F1EBD-2DB1-11D0-8C39-00C04FD9126B}")
$CLSID_CPStore = GUID$("{5A6F1EC3-2DB1-11D0-8C39-00C04FD9126B}")
$CLSID_CEnumTypes = GUID$("{09BB61E7-31EC-11D0-8C39-00C04FD9126B}")
$CLSID_CEnumItems = GUID$("{09BB61E6-31EC-11D0-8C39-00C04FD9126B}")
#ENDIF ' /* __PSTORECLib_LIBRARY_DEFINED__ */
' ########################################################################################
' IEnumPStoreItems interface
' IID = 5A6F1EC1-2DB1-11D0-8C39-00C04FD9126B
' Inherited interface = IUnknown
' ########################################################################################
#IF NOT %DEF(%IEnumPStoreItems_INTERFACE_DEFINED)
 %IEnumPStoreItems_INTERFACE_DEFINED = 1
$IID_IEnumPStoreItems = GUID$("{5A6F1EC1-2DB1-11D0-8C39-00C04FD9126B}")
INTERFACE IEnumPStoreItems $IID_IEnumPStoreItems
 INHERIT IUnknown
 ' =====================================================================================
 METHOD Next ( ' VTable offset = 12
 BYVAL celt AS DWORD
 , BYREF rgelt AS DWORD
 , BYREF pceltFetched AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Skip ( ' VTable offset = 16
 BYVAL celt AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Reset ( ' VTable offset = 20
 ) AS LONG
 ' =====================================================================================
 METHOD Clone ( ' VTable offset = 24
 BYREF ppenum AS IEnumPStoreItems
 ) AS LONG
 ' =====================================================================================
END INTERFACE
#ENDIF ' /* __IEnumPStoreItems_INTERFACE_DEFINED__ */
' ########################################################################################
' IEnumPStoreTypes interface
' IID = 789C1CBF-31EE-11D0-8C39-00C04FD9126B
' Inherited interface = IUnknown
' ########################################################################################
#IF NOT %DEF(%IEnumPStoreTypes_INTERFACE_DEFINED)
 %IEnumPStoreTypes_INTERFACE_DEFINED = 1
$IID_IEnumPStoreTypes = GUID$("{789C1CBF-31EE-11D0-8C39-00C04FD9126B}")
INTERFACE IEnumPStoreTypes $IID_IEnumPStoreTypes
 INHERIT IUnknown
 ' =====================================================================================
 METHOD Next ( ' VTable offset = 12
 BYVAL celt AS DWORD
 , BYREF rgelt AS GUID
 , BYREF pceltFetched AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Skip ( ' VTable offset = 16
 BYVAL celt AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Reset ( ' VTable offset = 20
 ) AS LONG
 ' =====================================================================================
 METHOD Clone ( ' VTable offset = 24
 BYREF ppenum AS IEnumPStoreTypes
 ) AS LONG
 ' =====================================================================================
END INTERFACE
#ENDIF ' /* __IEnumPStoreTypes_INTERFACE_DEFINED__ */
' ########################################################################################
' IPStore interface
' IID = 5A6F1EC0-2DB1-11D0-8C39-00C04FD9126B
' Inherited interface = IUnknown
' ########################################################################################
#IF NOT %DEF(%IPStore_INTERFACE_DEFINED)
 %IPStore_INTERFACE_DEFINED = 1
$IID_IPStore = GUID$("{5A6F1EC0-2DB1-11D0-8C39-00C04FD9126B}")
INTERFACE IPStore $IID_IPStore
 INHERIT IUnknown
 ' =====================================================================================
 METHOD GetInfo ( ' VTable offset = 12
 BYREF ppProperties AS PST_PROVIDERINFO
 ) AS LONG
 ' =====================================================================================
 METHOD GetProvParam ( ' VTable offset = 16
 BYVAL dwParam AS DWORD
 , BYREF pcbData AS DWORD
 , BYREF ppbData AS DWORD
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD SetProvParam ( ' VTable offset = 20
 BYVAL dwParam AS DWORD
 , BYVAL cbData AS DWORD
 , BYVAL pbData AS BYTE PTR
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD CreateType ( ' VTable offset = 24
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pInfo AS PST_TYPEINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD GetTypeInfo ( ' VTable offset = 28
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF ppInfo AS PST_TYPEINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD DeleteType ( ' VTable offset = 32
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD CreateSubtype ( ' VTable offset = 36
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pSubtype AS GUID
 , BYREF pInfo AS PST_TYPEINFO
 , BYREF pRules AS PST_ACCESSRULESET
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD GetSubtypeInfo ( ' VTable offset = 40
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pSubtype AS GUID
 , BYREF ppInfo AS PST_TYPEINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD DeleteSubtype ( ' VTable offset = 44
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pSubtype AS GUID
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD ReadAccessRuleset ( ' VTable offset = 48
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pSubtype AS GUID
 , BYREF ppRules AS PST_ACCESSRULESET
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD WriteAccessRuleset ( ' VTable offset = 52
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYREF pSubtype AS GUID
 , BYREF pRules AS PST_ACCESSRULESET
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD EnumTypes ( ' VTable offset = 56
 BYVAL Key AS DWORD
 , BYVAL dwFlags AS DWORD
 , BYREF ppenum AS IEnumPStoreTypes
 ) AS LONG
 ' =====================================================================================
 METHOD EnumSubtypes ( ' VTable offset = 60
 BYVAL Key AS DWORD
 , BYREF pType AS GUID
 , BYVAL dwFlags AS DWORD
 , BYREF ppenum AS IEnumPStoreTypes
 ) AS LONG
 ' =====================================================================================
 METHOD DeleteItem ( ' VTable offset = 64
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYREF szItemName AS WSTRINGZ
 , BYREF pPromptInfo AS PST_PROMPTINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD ReadItem ( ' VTable offset = 68
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYREF szItemName AS WSTRINGZ
 , BYREF pcbData AS DWORD
 , BYREF ppbData AS DWORD
 , BYREF pPromptInfo AS PST_PROMPTINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD WriteItem ( ' VTable offset = 72
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYREF szItemName AS WSTRINGZ
 , BYVAL cbData AS DWORD
 , BYVAL pbData AS BYTE PTR
 , BYREF pPromptInfo AS PST_PROMPTINFO
 , BYVAL dwDefaultConfirmationStyle AS DWORD
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD OpenItem ( ' VTable offset = 76
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYREF szItemName AS WSTRINGZ
 , BYVAL ModeFlags AS DWORD
 , BYREF pPromptInfo AS PST_PROMPTINFO
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD CloseItem ( ' VTable offset = 80
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYREF szItemName AS WSTRINGZ
 , BYVAL dwFlags AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD EnumItems ( ' VTable offset = 84
 BYVAL Key AS DWORD
 , BYREF pItemType AS GUID
 , BYREF pItemSubtype AS GUID
 , BYVAL dwFlags AS DWORD
 , BYREF ppenum AS IEnumPStoreItems
 ) AS LONG
 ' =====================================================================================
END INTERFACE
#ENDIF ' /* __IPStore_INTERFACE_DEFINED__ */
' ########################################################################################
' IEnumPStoreProviders interface
' IID = 5A6F1EBF-2DB1-11D0-8C39-00C04FD9126B
' Inherited interface = IUnknown
' ########################################################################################
#IF NOT %DEF(%IEnumPStoreProviders_INTERFACE_DEFINED)
 %IEnumPStoreProviders_INTERFACE_DEFINED = 1
$IID_IEnumPStoreProviders = GUID$("{5A6F1EBF-2DB1-11D0-8C39-00C04FD9126B}")
INTERFACE IEnumPStoreProviders $IID_IEnumPStoreProviders
 INHERIT IUnknown
 ' =====================================================================================
 METHOD Next ( ' VTable offset = 12
 BYVAL celt AS DWORD
 , BYREF rgelt AS PST_PROVIDERINFO
 , BYREF pceltFetched AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Skip ( ' VTable offset = 16
 BYVAL celt AS DWORD
 ) AS LONG
 ' =====================================================================================
 METHOD Reset ( ' VTable offset = 20
 ) AS LONG
 ' =====================================================================================
 METHOD Clone ( ' VTable offset = 24
 BYREF ppenum AS IEnumPStoreProviders
 ) AS LONG
 ' =====================================================================================
END INTERFACE
#ENDIF ' /* __IEnumPStoreProviders_INTERFACE_DEFINED__ */
'HRESULT __stdcall PStoreCreateInstance(
' IPStore __RPC_FAR *__RPC_FAR *ppProvider,
' PST_PROVIDERID __RPC_FAR *pProviderID,
' void __RPC_FAR *pReserved,
' DWORD dwFlags);
FUNCTION PStoreCreateInstance (BYREF ppProvider AS IPStore, BYREF pProviderID AS GUID, BYVAL pReserved AS DWORD, BYVAL dwFlags AS DWORD) AS LONG
 LOCAL hr AS LONG
 LOCAL hLib AS DWORD
 LOCAL pProc AS DWORD
 hLib = LoadLibrary("Pstorec.dll")
 IF hLib = %NULL THEN
 FUNCTION = GetLastError
 EXIT FUNCTION
 END IF
 pProc = GetProcAddress(hLib, "PStoreCreateInstance")
 IF pProc = %NULL THEN
 hr = GetLastError
 ELSE
 CALL DWORD pProc USING PStoreCreateInstance(ppProvider, pProviderID, pReserved, dwFlags) TO hr
 END IF
 FreeLibrary hLib
 FUNCTION = hr
END FUNCTION
'HRESULT __stdcall PStoreEnumProviders(
' DWORD dwFlags,
' IEnumPStoreProviders __RPC_FAR *__RPC_FAR *ppenum);
FUNCTION PStoreEnumProviders (BYVAL dwFlags AS DWORD, BYREF ppenum AS IEnumPStoreProviders) AS LONG
 LOCAL hr AS LONG
 LOCAL hLib AS DWORD
 LOCAL pProc AS DWORD
 hLib = LoadLibrary("Pstorec.dll")
 IF hLib = %NULL THEN
 FUNCTION = GetLastError
 EXIT FUNCTION
 END IF
 pProc = GetProcAddress(hLib, "PStoreEnumProviders")
 IF pProc = %NULL THEN
 hr = GetLastError
 ELSE
 CALL DWORD pProc USING PStoreEnumProviders(dwFlags, ppenum) TO hr
 END IF
 FreeLibrary hLib
 FUNCTION = hr
END FUNCTION
#ENDIF
