home *** CD-ROM | disk | FTP | other *** search
- // ====================================================================
- //
- // File: tree.cpp
- //
- // Copyright (c) 1994, 1995 Microsoft Corp.
- //
- // Author:
- // Jonathan Shuval Microsoft Corp.
- //
- //
- // This sample builds a tree of the container/folder hierarchy and
- // displays it to the console.
- //
- // The information that is displayed is as follows:
- // For each container we display the container's type and tag followed
- // by a list of filters (possibly empty). This lists filters that are
- // acted upon directly at that level.
- // Following the filter list is a folder list. This gives the folder's
- // type and tag, its filter list, and then a list of scalars for the
- // folder.
- // The scalar display shows the scalar name, it's type, and its access
- // mode.
- //
- // See the readme.txt file in this directory for more information.
- //
- // ====================================================================
-
-
- // ====================================================================
- //
- // Includes
- //
- // ====================================================================
- #include <afx.h>
- #include <smsapi.h>
-
-
- // ====================================================================
- //
- // Defines.
- //
- // ====================================================================
- #define CCH_MAXSTRING 256
-
-
- // ====================================================================
- //
- // Prototypes.
- //
- // ====================================================================
-
- // Process a container.
- // -------------------------------------------------------------
- void doContainer( FOLDER_INFO *pContainer );
-
-
- // Process a folder.
- // -------------------------------------------------------------
- void doFolder( DWORD folderType, int indent, DWORD dwConType );
-
-
- // Adds a container to the container list.
- // -------------------------------------------------------------
- void AddContainer( DWORD dwConType );
-
-
- // Given a filter type display its properties.
- // -------------------------------------------------------------
- void doFilter( DWORD dwFilterType, int indent );
-
-
- // Locates filter of specified type from the global filter list.
- // -------------------------------------------------------------
- FILTER_INFO *FindFilter( DWORD filterType );
-
-
- // Mark folder as already enumerated within this container graph.
- // -------------------------------------------------------------
- void Enumerated( DWORD dwConType, DWORD folderType );
-
-
- // Call this to find out if this foldertype already been
- // enumerated within this container graph.
- // -------------------------------------------------------------
- BOOL IsEnumerated(DWORD dwConType, DWORD folderType);
-
-
- // Prompt the user for input and return the reply.
- // -------------------------------------------------------------
- void InputString( const char *pszMessage, char *pszResult );
-
-
- // Display the help message.
- // -------------------------------------------------------------
- void DisplayHelp();
-
- // Display the greeting.
- // -------------------------------------------------------------
- void DisplayGreeting();
-
-
- // Check to see if there was a request for help
- // on the command line.
- // -------------------------------------------------------------
- BOOL DidRequestHelp( int argc, char **argv );
-
-
-
-
-
- // ====================================================================
- //
- // Globals.
- //
- // ====================================================================
- FOLDER_INFO **gpFolders = NULL; // List of FOLDER_INFOs.
- DWORD gctFolders = 0; // Count of them.
-
-
- FILTER_INFO *gpFilters = NULL; // List of FILTER_INFOs.
- DWORD gctFilters = 0; // Count of them.
-
- //
- // This struct is used to hold information about what folders
- // have already been enumerated for a particular container.
- //
- typedef struct tagContainerEntry {
- DWORD dwConType; // Container's type.
- CDWordArray aEnumFolders; // Folders already enumerated.
- } ContainerEntry;
-
-
- CObArray ContainerList; // List of containers (contains list
- // of ContainerEntry structs.)
-
-
-
-
-
- // ====================================================================
- //
- // Start here.
- //
- // ====================================================================
- void main( int argc, char** argv )
- {
- // Check to see if this is a request to display the help
- // screen. If so, display it. Otherwise, display a greeting
- // banner.
- //=========================================================
- if (DidRequestHelp( argc, argv )) {
- DisplayHelp();
- return;
- }
- else {
- DisplayGreeting();
- }
-
-
-
- // Data.
- // =====
-
- DWORD ctContainers;
- FOLDER_INFO **pContainers = NULL;
- FOLDER_INFO *pCont = NULL;
-
-
-
-
- // Enumerate containers.
- // =====================
-
- // Get number of containers.
- SmsEnumContainers( NULL, &ctContainers );
-
- // Allocate memory and get the containers.
- pContainers = new FOLDER_INFO *[ctContainers];
- SmsEnumContainers( pContainers, &ctContainers );
-
-
- // Enumerate all filters.
- // ======================
- // Get number of filters.
- SmsEnumFilters(NULL, &gctFilters);
-
- // Allocate memory and get the filters.
- gpFilters = new FILTER_INFO[gctFilters];
- SmsEnumFilters( gpFilters, &gctFilters );
-
-
- // Enumerate all folders.
- // ======================
- // Get number of folders.
- SmsEnumFolders( NULL, &gctFolders );
-
- // Allocate memory and get the folders.
- gpFolders = new FOLDER_INFO *[gctFolders];
- SmsEnumFolders( gpFolders, &gctFolders );
-
-
- // Loop through each container.
- // ============================
-
- for (DWORD i = 0; i < ctContainers; i++) {
-
- // Process the container
- doContainer( pContainers[i] );
- }
-
- }
-
-
-
- // ====================================================================
- //
- // doContainer -- process container.
- //
- // This is called from main. We print out information for this
- // container, and then process each folder within the container.
- //
- // ====================================================================
-
- void doContainer( FOLDER_INFO *pContainer )
- {
- DWORD dwI;
-
- // Add this container to our container list.
- // =========================================
- AddContainer( pContainer->dwTag );
-
- // We are now looking at the FOLDER_INFO for a container.
- // We want to print out the count and list of filters,
- // the folder type count, and then process each folder.
- // ======================================================
- printf("Container: %s [%d]\n", pContainer->pszTag, pContainer->dwTag);
-
- // Print out list of filters.
- // =============================
- printf("%d filter(s)\n", pContainer->ctFilters);
- DWORD *pFilters = pContainer->pFilterTags;
-
- for (dwI = 0; dwI < pContainer->ctFilters; dwI++) {
- doFilter( pFilters[dwI], 1 );
- }
-
-
- // Print out list of folders.
- // ==========================
- printf("%d folder-type(s)\n", pContainer->ctFolders);
-
- DWORD *pFolderIDs = pContainer->pFolderTags;
- for (dwI = 0; dwI < pContainer->ctFolders; dwI++) {
-
- // Now cause the folder to print himself out.
- // ------------------------------------------
- doFolder( pFolderIDs[dwI], 1, pContainer->dwTag );
- }
-
- // No scalars for container.
- // =========================
-
- printf("\n\n");
- }
-
-
-
- // ====================================================================
- //
- // FindFilter -- locate filter of specified type from the list of
- // filter descriptors returned by the API SmsEnumFilters.
- //
- // Return a pointer to the FILTER_INFO for the filter.
- //
- // Called from doFilter.
- //
- // ====================================================================
-
- FILTER_INFO *FindFilter( DWORD filterType )
- {
- FILTER_INFO *pFI;
- for (DWORD dwI = 0; dwI < gctFilters; dwI++) {
- pFI = &gpFilters[dwI];
- if (pFI->filterType == filterType) {
- return(pFI);
- }
- }
-
- return(NULL);
- }
-
-
- // ====================================================================
- //
- // dumpScalar -- given a SCALAR_INFO, display the scalar.
- //
- // We display the scalar's name, type, and access mode.
- //
- // Params:
- // SCALAR_INFO Scalar to display.
- // indent indent level
- //
- //
- // ====================================================================
-
- void dumpScalar( SCALAR_INFO *pSc, int indent )
- {
- // Indentation.
- // ============
- char szIndent[100];
- memset( szIndent, '\0', 100 );
- for (int iLevel = 0; iLevel < indent; iLevel++) {
- strcat( szIndent, "\t");
- }
-
- char *pszType, *pszAccess;
-
- // Determine scalar type, display accordingly.
- // ===========================================
- switch (pSc->scType) {
- case SCALAR_STRING:
- pszType = "string"; break;
-
- case SCALAR_INT:
- pszType = "integer"; break;
-
- case SCALAR_TIME:
- pszType = "time"; break;
-
- case SCALAR_BINARY:
- pszType = "binary"; break;
- }
-
- // Determine access mode, display accordingly.
- // ===========================================
- switch (pSc->fAccess) {
- case ACCESS_READ:
- pszAccess = "read"; break;
-
- case ACCESS_CREATE:
- pszAccess = "create"; break;
-
- case ACCESS_MODIFY:
- pszAccess = "modify"; break;
-
- case ACCESS_DELETE:
- pszAccess = "delete"; break;
- }
-
-
- printf("%s%s (%s, %s)\n", szIndent, pSc->szName, pszType, pszAccess);
-
- }
-
-
-
- // ====================================================================
- //
- // doScalars -- display a folder's scalar.
- //
- // Loop through the list of SCALAR structures that are embedded in the
- // FOLDER_INFO, and display them.
- //
- // The 'indent' parameter says how far to indent the resulting display
- // string so it looks almost presentable.
- //
- // Params:
- // FOLDER_INFO *pFolder The structure describing the folder
- // under consideration.
- // int indent Indent level.
- //
- // Returns:
- // Nothing.
- //
- // ====================================================================
-
- void doScalars( FOLDER_INFO *pFolder, int indent )
- {
- SCALAR_INFO *pScalar;
-
- for (DWORD dwI = 0; dwI < pFolder->ctScalars; dwI++) {
- pScalar = &pFolder->pScalars[dwI];
- dumpScalar( pScalar, indent );
- }
- }
-
-
- // ====================================================================
- //
- // doFolder -- Given a folder type print out this folder's information.
- //
- // The folder has already been retrieved in SmsEnumFolders, we just
- // access it from there.
- //
- // Params:
- // folderType Folder type we're interested in.
- // dwConType Container's type.
- //
- // Returns:
- // Nothing.
- //
- // ====================================================================
-
- void doFolder( DWORD folderType, int indent, DWORD dwConType )
- {
-
- FOLDER_INFO *pFolder;
- DWORD dwI;
- BOOL bFound = FALSE;
-
- // Indentation.
- // ============
- char szIndent[100];
- memset( szIndent, '\0', 100 );
- for (int iLevel = 0; iLevel < indent; iLevel++) {
- strcat( szIndent, "\t");
- }
-
-
- // Loop through the retrieved folders looking for
- // the one with a tag for folderType.
- // ==============================================
- for (dwI = 0; dwI < gctFolders; dwI++) {
- pFolder = gpFolders[dwI];
- if (pFolder->dwTag == folderType) {
- bFound = TRUE;
- break;
- }
- }
-
-
- if (!bFound) {
- printf("<<< Error: couldn't locate folder %d >>>\n", folderType);
- return;
- }
-
-
- // Display folder type and tag and filter count.
- // =============================================
- printf("%s********** %s folder [%d] **********\n",
- szIndent, pFolder->pszTag, pFolder->dwTag);
-
- // Check to see if it's already been displayed.
- // We only want to do this in the context of the current container.
- // ----------------------------------------------------------------
- if (IsEnumerated(dwConType, folderType)) {
- printf("%sFolder already enumerated in this container\n", szIndent);
- printf("%s********** End of %s folder **********\n\n",
- szIndent, pFolder->pszTag );
- return;
- }
-
- printf("%s%d filter(s)\n", szIndent, pFolder->ctFilters);
-
- // Print out list of filter types.
- // ===============================
- DWORD *pFilters = pFolder->pFilterTags;
-
- for (dwI = 0; dwI < pFolder->ctFilters; dwI++) {
- doFilter( pFilters[dwI], indent );
- }
-
- // Print out number of scalars, then display them.
- // ===============================================
- printf("%s%d scalars\n", szIndent, pFolder->ctScalars);
- doScalars( pFolder, indent );
-
-
- // Prepare to display sub-folders.
- // ===============================
- printf("%s%d folder-type(s)\n", szIndent, pFolder->ctFolders);
-
-
- // Before processing sub-folder types mark this folder as already
- // enumerated in this container. Prevents infinite recursion.
- Enumerated(dwConType, folderType);
-
- // Print out list of folder types.
- DWORD *pFolderIDs = pFolder->pFolderTags;
- for (dwI = 0; dwI < pFolder->ctFolders; dwI++) {
- // Now cause the folder to print himself out.
- doFolder( pFolderIDs[dwI], indent+1, dwConType );
-
- }
-
- printf("%s********** End of %s folder **********\n\n",
- szIndent, pFolder->pszTag );
-
- }
-
-
-
- // ====================================================================
- //
- // doFilter -- given a filter type display its properties.
- //
- // Called from doContainer and doFolder.
- //
- // ====================================================================
-
- void doFilter( DWORD dwFilterType, int indent )
- {
-
- FILTER_INFO *pFilter = FindFilter( dwFilterType );
-
- if (!pFilter) {
- printf("<<< Error: couldn't locate filter %d >>>\n", dwFilterType);
- return;
- }
-
- // Indentation.
- // ============
- char szIndent[100];
- memset( szIndent, '\0', 100 );
- for (int iLevel = 0; iLevel < indent; iLevel++) {
- strcat( szIndent, "\t");
- }
-
- // Display filter type and tag.
- // ============================
- printf("%s%s (%d)\n", szIndent, pFilter->szTag, dwFilterType);
-
-
- // Display filter properties.
- // ==========================
- char *ppszField[10]; // Store pointers here.
- DWORD ctFields = 0; // Number of pointers.
-
- char szBuff[256]; // Build up output string here.
- sprintf(szBuff, "%s\t[", szIndent); // Additional level of indent.
-
- if (*(pFilter->szName)) {
- ppszField[ctFields++] = "Token.szName = ";
- ppszField[ctFields++] = pFilter->szName;
- }
-
- if (*(pFilter->szValue)) {
- ppszField[ctFields++] = "Token.szValue = ";
- ppszField[ctFields++] = pFilter->szValue;
- }
-
- if (*(pFilter->szOperator)) {
- ppszField[ctFields++] = "Token.szOperator = ";
- ppszField[ctFields++] = pFilter->szOperator;
- }
-
- if (*(pFilter->szArchitecture)) {
- ppszField[ctFields++] = "Token.szArchitecture = ";
- ppszField[ctFields++] = pFilter->szArchitecture;
- }
-
- if (*(pFilter->szGroupClass)) {
- ppszField[ctFields++] = "Token.szGroupClass = ";
- ppszField[ctFields++] = pFilter->szGroupClass;
- }
-
- if (*(pFilter->szAttributeName)) {
- ppszField[ctFields++] = "Token.szAttributeName = ";
- ppszField[ctFields++] = pFilter->szAttributeName;
- }
-
-
- for (DWORD dwI = 0; dwI < ctFields; dwI += 2) {
- printf("\t%s%s\"%s\"\n", szIndent, ppszField[dwI], ppszField[dwI+1]);
- }
-
-
- }
-
-
-
- // ====================================================================
- //
- // AddContainer -- adds a container to the container list.
- //
- // This is only for detecting folders that have already been
- // enumerated. Nothing more.
- // Trouble is we duplicate!
- //
- // ====================================================================
-
- void AddContainer( DWORD dwConType )
- {
- ContainerEntry *pCEntry;
- pCEntry = new ContainerEntry;
- pCEntry->dwConType = dwConType;
-
- ContainerList.Add((CObject *)pCEntry );
- }
-
-
-
- // ====================================================================
- //
- // Enumerated -- Mark this folder as already enumerated within this
- // container graph.
- //
- // ====================================================================
-
- void Enumerated(DWORD dwConType, DWORD folderType)
- {
- // Locate the container.
- BOOL bFound = FALSE;
- DWORD dwI; // loop index.
- ContainerEntry *pCEntry;
-
- // We keep a global ContainerList (CObArray) which contains
- // a list of container entries (above).
-
- // Locate container entry.
- // =======================
- for (dwI = 0; dwI < (DWORD)ContainerList.GetSize(); dwI++) {
- pCEntry = (ContainerEntry *)ContainerList[dwI];
- if (pCEntry->dwConType == dwConType) {
- bFound = TRUE;
- break;
- }
- }
-
- if (!bFound) {
- printf("<<< Error: container tag %d not found in list >>>\n", dwConType);
- return;
- }
-
- // Add this folder to our list of enumerated folders.
- // ==================================================
- pCEntry->aEnumFolders.Add( folderType );
-
- }
-
-
-
- // ====================================================================
- //
- // IsEnumerated -- Has this foldertype already been enumerated within
- // this container graph?
- //
- // ====================================================================
-
- BOOL IsEnumerated(DWORD dwConType, DWORD folderType)
- {
- BOOL bFound = FALSE;
- DWORD dwI; // loop index.
- ContainerEntry *pCEntry;
-
- // We keep a global ContainerList (CObArray) which contains
- // a list of container entries (above).
-
- // Locate container entry.
- // =======================
- for (dwI = 0; dwI < (DWORD)ContainerList.GetSize(); dwI++) {
- pCEntry = (ContainerEntry *)ContainerList[dwI];
- if (pCEntry->dwConType == dwConType) {
- bFound = TRUE;
- break;
- }
- }
-
- if (!bFound) {
- printf("<<< Error: container tag %d not found in list >>>\n", dwConType);
- return(FALSE);
- }
-
- // Now look through the array of enumerated folders.
- // =================================================
- for (dwI = 0; dwI < (DWORD)pCEntry->aEnumFolders.GetSize(); dwI++) {
- if (pCEntry->aEnumFolders[dwI] == folderType) {
-
- // Found it. Folder already enumerated.
- // ------------------------------------
- return(TRUE);
- }
- }
-
- // Folder hasn't been enumerated.
- // ------------------------------
- return(FALSE);
- }
-
-
-
-
-
- // ====================================================================
- // InputString
- //
- // Prompt the user to input a string and return the string in the
- // specified buffer.
- //
- // Parameters:
- // const char* pszMessage
- // The user prompt to display.
- //
- // char* pszResult
- // Pointer to the buffer where the user's input will be returned.
- //
- // Returns;
- // The user's input is returned via the given buffer.
- //
- // ====================================================================
- void InputString( const char *pszMessage, char *pszResult)
- {
- printf("%s: ", pszMessage);
- gets(pszResult);
- }
-
-
-
-
-
-
-
-
- // ====================================================================
- // DidRequestHelp
- //
- // Check the program's arguments to see if the user asked for
- // the help screen to be displayed.
- //
- // Parameters:
- // int argc
- // The argc value from main(argc, argv)
- //
- // char** argv
- // The argv value from main(argc, argv)
- //
- // Returns:
- // TRUE if command line parameters included a request
- // for help to be displayed.
- //
- // ====================================================================
- BOOL DidRequestHelp(int argc, char** argv)
- {
- if (argc == 2 && (strcmp(argv[1], "-help") == 0)) {
- return(TRUE);
- }
- else {
- return(FALSE);
- }
- }
-
-
- // ====================================================================
- // DisplayHelp
- //
- // This function displays the samples help screen.
- //
- // Parameters:
- // None
- //
- // Returns:
- // Nothing.
- //
- // ====================================================================
- void DisplayHelp()
- {
- // Version information.
- // ====================
- char *pVer;
- SmsAPIVer( &pVer );
- printf("\n%s\n\n", pVer);
-
-
- // Description.
- // ============
-
- printf("********************************************************************\n");
- printf("* tree.exe: *\n");
- printf("* *\n");
- printf("* This is a sample program for the SMS SDK. It shows how the *\n");
- printf("* container hierarchy can be displayed. *\n");
- printf("* *\n");
- printf("* For each container in SMS, the following details are displayed: *\n");
- printf("* the container's tag and type *\n");
- printf("* any filters that are acted upon directly by the container *\n");
- printf("* *\n");
- printf("* Following this is a display of all folders within that container.*\n");
- printf("* *\n");
- printf("* For folders the following is displayed: *\n");
- printf("* the folder's type and tag *\n");
- printf("* any filters that are acted upon by the folder *\n");
- printf("* a list of the folder's scalars *\n");
- printf("* Note that folder enumeration is recursive, that is, some folders *\n");
- printf("* contain sub-folders. *\n");
- printf("* *\n");
- printf("* For filters a list of the filter's attributes are displayed. *\n");
- printf("* *\n");
- printf("* Syntax: *\n");
- printf("* tree.exe [-help] *\n");
- printf("* *\n");
- printf("* Switches: *\n");
- printf("* -help Display this help screen. *\n");
- printf("* *\n");
- printf("********************************************************************\n");
- printf("\n");
- }
-
-
-
- // ====================================================================
- // DisplayGreeting
- //
- // Display the initial greeting banner.
- //
- // Parameters:
- // None.
- //
- // Returns:
- // Nothing.
- //
- // ====================================================================
- void DisplayGreeting()
- {
- // For this sample, the greeting is identical to the help screen.
- //===============================================================
- DisplayHelp();
-
- // Pause so the description doesn't fly off the screen.
- // ====================================================
- char szReply[CCH_MAXSTRING];
- InputString("Press ENTER to continue", szReply);
- printf("\n");
- }
-
-
-
-
-
-
- /* EOF: tree.cpp */
-
-