home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / ADSDK.ZIP / Samples / ActiveDir / CreateUser / vc / main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-13  |  28.7 KB  |  900 lines

  1.  
  2. #define INC_OLE2
  3. #define UNICODE 1
  4. #define _WIN32_DCOM
  5.  
  6. #include <windows.h>
  7. #include <winuser.h>
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <malloc.h>
  13. #include <winldap.h>
  14.  
  15. #include <activeds.h>
  16. #include <assert.h>
  17.  
  18. #include "CreateUserHelpers.h"
  19. #include "UserProps.h"
  20.  
  21.  
  22. //#include "AttributesList.h"
  23. #define MAX_ATTRIBS 4096
  24.  
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////
  26. // String for usage information
  27. WCHAR * pwszUsage = L"Creates new User under the passed container.\n"
  28.                     L"Usage:\n"
  29.                     L"CreateUser\n"
  30.                     L"        <*> Simple New User Information <*>\n"
  31.                     L"            /LDAP <Path of container>\n" 
  32.                     L"              ADsPath of the container for placing the new group\n"
  33.                     L"           /UNAME <NT 5 User Name> \n"
  34.                     L"              This is the name for the new group\n"
  35.                     L"           /SAMNAME <Downlevel NT 4 Sam Account name>\n"
  36.                     L"              Cannot exceed 20 characters and must be globally unique\n"
  37.                     L"\n"
  38.                     L"        <*> Detailed New User information <*>\n"
  39.                     L"            /FILE < Info File >\n"
  40.                     L"              Filename for file to contain new user information\n"
  41.                     L"\n"
  42.                     L"        <*> OPTIONAL Binding Information <*>\n"
  43.                     L"           /USER <User name used for binding to the DC>\n"
  44.                     L"           /PASS <Password used for binding to the DC>\n"
  45.                     L"           (If these are passed, binding is done with ADsOpenObject())\n"
  46.                     L"\n"         
  47.                     L"\n";
  48.  
  49.  
  50. // Sample command line:
  51.  
  52. //    /LDAP "LDAP://nttest.microsoft.com/CN=UGExercise Sample Container,dc=nttest,dc=microsoft,dc=com" /UNAME BOB /SAMNAME BOB /USER Administrator /PASS ""
  53.  
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////
  55. // Module level global variables
  56.  
  57. BSTR bsLDAP     = NULL; // <Path of container> ADsPath of the container for placing the new group
  58.     
  59. BSTR bsUNAME    = NULL; // <NT 5 User Name> This is the name for the new group
  60.     
  61. BSTR bsSAMNAME  = NULL; // <Downlevel NT 4 Sam Account name> Cannot exceed 20 characters and must be globally unique
  62.  
  63. BSTR bsFILE     = NULL; // < Info File > Filename for file to contain new user information
  64.  
  65. BSTR bsUSER     = NULL; // <User name used for binding to the DC>
  66.     
  67. BSTR bsPASS     = NULL; // <Password used for binding to the DC>
  68.  
  69. ////////////////////////////////////////////////////////////////////////////////////////////////////
  70. // Forward Declarations
  71. BOOL    ParseCommandLine( int argc, wchar_t *argv[ ]);
  72. HRESULT CreateUser(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IDirectoryObject ** ppDirObjRet);
  73. void    Trim(LPWSTR pwszData);
  74. HRESULT CreateUserFromFile(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IDirectoryObject ** ppDirObjRet,LPWSTR pwszFileName);
  75. BOOL    GetNextLine(FILE* fp,LPWSTR pwszDest,int iSize);
  76. void    RemoveSpecialChars(LPWSTR pwszLine);
  77.  
  78. ////////////////////////////////////////////////////////////////////////////////////////////////////
  79. // main()
  80.  
  81. /* Note: Using the UNICODE version of main().
  82.    this removes the need for the sample to include
  83.    UNICODE-ANSI conversion routines
  84. */
  85. void wmain( int argc, wchar_t *argv[ ])
  86. {
  87.     WCHAR pwszTemp[4096];
  88.     
  89.     // We have now scanned PAST whitespace- so copy the string:
  90.     wcscpy(pwszTemp,L" A String");
  91.  
  92.     Trim(pwszTemp);
  93.  
  94.     HRESULT hr;
  95.     IDirectoryObject * pDirObjectContainer = NULL;
  96.     IDirectoryObject * pDirObjRet = NULL;
  97.  
  98.     // Initialize COM
  99.     CoInitialize(0);
  100.  
  101.     if (!ParseCommandLine(argc,argv))
  102.         return;
  103.  
  104.     // Bind to the container passed 
  105.     // If USER and PASS passed in, use ADsOpenObject()
  106.     if (bsUSER)
  107.         hr = ADsOpenObject(bsLDAP, bsUSER, bsPASS, 
  108.                                    ADS_SECURE_AUTHENTICATION,IID_IDirectoryObject, (void**) &pDirObjectContainer);
  109.     else
  110.         hr = ADsGetObject(  bsLDAP, IID_IDirectoryObject,(void **)&pDirObjectContainer);
  111.     
  112.     if (SUCCEEDED(hr))
  113.     {
  114.         // if a file is NOT passed in- Do the simple version
  115.         if (!bsFILE)
  116.         {
  117.             // Call the helper funtion to create the User
  118.             hr = CreateUser(pDirObjectContainer, bsUNAME,bsSAMNAME,
  119.                              &pDirObjRet);
  120.         }
  121.         else // file was passed in
  122.         {
  123.             // Call the helper funtion to create the User
  124.             hr = CreateUserFromFile(pDirObjectContainer, bsUNAME,bsSAMNAME,
  125.                                     &pDirObjRet,bsFILE);
  126.         }        
  127.         if (SUCCEEDED(hr))
  128.         {
  129.             _putws(L"\n\n New User created with the following properties:\n");
  130.         
  131.             IADs * pIADsNewGoup = NULL;
  132.         
  133.             // User succeeded- now get an IADs interface to it 
  134.             // and print some properties
  135.             hr = pDirObjRet->QueryInterface(IID_IADs,(void**)&pIADsNewGoup);
  136.  
  137.             if (SUCCEEDED(hr))
  138.             {
  139.                 PrintIADSObject(pIADsNewGoup);
  140.                         
  141.                 pIADsNewGoup->Release();
  142.                 pIADsNewGoup = NULL;
  143.             }
  144.             else
  145.                 CheckADHRESULT(hr,L"QueryInterface() - New User for IADs");
  146.             pDirObjRet->Release();
  147.             pDirObjRet = NULL;    
  148.         }
  149.         else
  150.             CheckADHRESULT(hr,L"CreateUser()");
  151.  
  152.         pDirObjectContainer->Release();
  153.         pDirObjectContainer = NULL;    
  154.     }
  155.     else
  156.         if (bsUSER)
  157.             CheckADHRESULT(hr,L"ADsOpenObject()");
  158.         else
  159.             CheckADHRESULT(hr,L"ADsGetObject()");
  160.  
  161.     CoUninitialize();
  162.  }
  163.  
  164.  
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////
  166. /*
  167.     ParseCommandLine()- Parses command line and sets module level globals
  168.     
  169.     Parameters:
  170.  
  171.         int argc            - Number of Arguments
  172.         wchar_t *argv[ ]    - Array of arguments
  173.  
  174.     Returns:
  175.         TRUE if Command line was successfully parsed
  176.  
  177.     Affectets global variables:
  178.  
  179.         BSTR bsLDAP    
  180.         BSTR bsUNAME   
  181.         BSTR bsSAMNAME 
  182.         BSTR bsFILE    
  183.         BSTR bsUSER    
  184.         BSTR bsPASS    
  185. */    
  186.  
  187. BOOL ParseCommandLine( int argc, wchar_t *argv[ ])
  188. {
  189. /*
  190.      ** PARSE the FOLLOWING ARGUMENTS:
  191.     /LDAP <Path of container>
  192.         ADsPath of the container for placing the new group
  193.     
  194.     /UNAME <NT 5 User Name>
  195.         This is the name for the new group
  196.     
  197.     /SAMNAME <Downlevel NT 4 Sam Account name>
  198.         Cannot exceed 20 characters and must be globally unique
  199.  
  200.     <*> Detailed New User information <*>
  201.     /FILE < Info File >
  202.     
  203.         Filename for file to contain new user information
  204.  
  205.     <*> OPTIONAL Binding Information <*>
  206.     /USER <User name used for binding to the DC>
  207.     
  208.     /PASS <Password used for binding to the DC>
  209.     (If these are passed, binding is done with ADsOpenObject())
  210. */        
  211.     if (argc == 1)
  212.     {
  213.         _putws(pwszUsage);
  214.         return FALSE;
  215.     }
  216.     for (int x= 1; x < argc; x++)
  217.     {
  218.         if (_wcsicmp(argv[x],L"/LDAP")==0)
  219.         {
  220.             if (argc == x) // Make sure the parameter was passed
  221.             {
  222.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  223.                 _putws(pwszUsage);
  224.                 return FALSE;
  225.             }
  226.             // Go to the next argument and save it in module level variable
  227.             x++;
  228.             bsLDAP = SysAllocString(argv[x]);                
  229.         }
  230.         else if (_wcsicmp(argv[x],L"/UNAME")==0)
  231.         {
  232.             if (argc == x) // Make sure the parameter was passed
  233.             {
  234.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  235.                 _putws(pwszUsage);
  236.                 return FALSE;
  237.             }
  238.             // Go to the next argument and save it in module level variable
  239.             x++;
  240.             bsUNAME = SysAllocString(argv[x]);                
  241.         }
  242.         else if (_wcsicmp(argv[x],L"/SAMNAME")==0)
  243.         {
  244.             if (argc == x) // Make sure the parameter was passed
  245.             {
  246.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  247.                 _putws(pwszUsage);
  248.                 return FALSE;
  249.             }
  250.             // Go to the next argument and save it in module level variable
  251.             x++;
  252.             bsSAMNAME = SysAllocString(argv[x]);                
  253.         }
  254.         else if (_wcsicmp(argv[x],L"/FILE")==0)
  255.         {
  256.             if (argc == x) // Make sure the parameter was passed
  257.             {
  258.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  259.                 _putws(pwszUsage);
  260.                 return FALSE;
  261.             }
  262.             // Go to the next argument and save it in module level variable
  263.             x++;
  264.             bsFILE = SysAllocString(argv[x]);                
  265.         }
  266.         else if (_wcsicmp(argv[x],L"/USER")==0)
  267.         {
  268.             if (argc == x) // Make sure the parameter was passed
  269.             {
  270.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  271.                 _putws(pwszUsage);
  272.                 return FALSE;
  273.             }
  274.             // Go to the next argument and save it in module level variable
  275.             x++;
  276.             bsUSER = SysAllocString(argv[x]);                
  277.         }
  278.         else if (_wcsicmp(argv[x],L"/PASS")==0)
  279.         {
  280.             if (argc == x) // Make sure the parameter was passed
  281.             {
  282.                 wprintf(L"\nERROR: %s Missing parameter!!!!\n\n",argv[x]);
  283.                 _putws(pwszUsage);
  284.                 return FALSE;
  285.             }
  286.             // Go to the next argument and save it in module level variable
  287.             x++;
  288.             bsPASS = SysAllocString(argv[x]);                
  289.         }
  290.         else
  291.         {
  292.                 wprintf(L"\nERROR: %s UNknown Argument\n\n",argv[x]);
  293.                 _putws(pwszUsage);
  294.                 return FALSE;
  295.         }
  296.     }
  297.     // Check if User is poassed, then password is required:
  298.     if (bsUSER || bsPASS)
  299.         if (!bsUSER || !bsPASS) // if either one is missing complain
  300.         {
  301.             _putws(L"\nERROR: If /USER is specified /PASS is required!");
  302.             return FALSE;
  303.         }                    
  304.       
  305.     return TRUE;
  306. }
  307.  
  308.  
  309. HRESULT ConvertUTCFromStringToUTCTime( LPWSTR pwszTime, SYSTEMTIME *pst)
  310. {
  311.     FILETIME ft;
  312.     TCHAR sz[3];
  313.     LPWSTR pszSrc = pwszTime;
  314.     SYSTEMTIME st;
  315.  
  316.     // Year
  317.     sz[0] = pszSrc[0];
  318.     sz[1] = pszSrc[1];
  319.     sz[2] = TEXT('\0');
  320.     st.wYear = (WORD)_wtoi(sz);
  321.     if (st.wYear < 50)
  322.     {
  323.         st.wYear += 2000;
  324.     }
  325.     else
  326.     {
  327.         st.wYear += 1900;
  328.     }
  329.     // Month
  330.     sz[0] = pszSrc[2];
  331.     sz[1] = pszSrc[3];
  332.     st.wMonth = (WORD)_wtoi(sz);
  333.     
  334.     // Day
  335.     sz[0] = pszSrc[4];
  336.     sz[1] = pszSrc[5];
  337.     st.wDay = (WORD)_wtoi(sz);
  338.  
  339.     // Hour
  340.     sz[0] = pszSrc[6];
  341.     sz[1] = pszSrc[7];
  342.     st.wHour = (WORD)_wtoi(sz);
  343.  
  344.     // Minute
  345.     sz[0] = pszSrc[8];
  346.     sz[1] = pszSrc[9];
  347.     st.wMinute = (WORD)_wtoi(sz);
  348.  
  349.     // Second
  350.     sz[0] = pszSrc[10];
  351.     sz[1] = pszSrc[11];
  352.     st.wSecond = (WORD)_wtoi(sz);
  353.     st.wMilliseconds = 0;
  354.  
  355.     // This gets us the day of week
  356.     SystemTimeToFileTime(&st, &ft);
  357.     FileTimeToSystemTime(&ft, &st);
  358.     *pst = st;
  359.     return S_OK;
  360. }
  361.  
  362.  
  363. ////////////////////////////////////////////////////////////////////////////////////////////////////
  364. /*  GetNextLine()   - Retrives a line from the passed file pointer
  365.     
  366.     Parameters
  367.  
  368.         FILE* fp        - File Pointer
  369.         LPWSTR pwszDest - Destination Buffer
  370.         int iSize       - Size of Destination Buffer 
  371. */
  372.  
  373. BOOL GetNextLine(FILE* fp,LPWSTR pwszDest,int iSize)
  374. {
  375.     //BOOL bRet;
  376.     WCHAR c =0 ;
  377.     int x = 0;
  378.     do 
  379.     {
  380.         if (x < iSize )
  381.         {
  382.             // Get a character
  383.             c = getwc(fp);
  384.             // Handle the end
  385.             if (x ==0 && ((char)c) == EOF )
  386.                 return FALSE;
  387.                     
  388.             // If it is NOT a carriage return - save the character
  389.             // (note the cast to (char): as EOF is a char -1.
  390.             // with a WIDE character this becomes 65535)
  391.             // so we cast DOWN the char to test for the potential -1
  392.             if (c!= '\r' && ((char)c) != EOF && c != '\n')
  393.                 pwszDest[x++] = c;
  394.             else
  395.                 break;
  396.         }            
  397.     } while (c != '\r' && c != EOF && c != '\n' && c !=65535);
  398.  
  399.     pwszDest[x] = NULL;
  400.     return TRUE;
  401. }
  402.  
  403.  
  404. ////////////////////////////////////////////////////////////////////////////////////////////////////
  405. /*  Trim()   - VERY simple function for removing left and right whitespace from a unicode string
  406.     
  407.     Parameters
  408.  
  409.         LPWSTR pwszData                 -   Data passed for trimming- Function will modify
  410. */
  411. void Trim(LPWSTR pwszData)
  412. {
  413.     int iscan=0;
  414.     int iput=0;
  415.  
  416.     int iLenData = wcslen(pwszData);
  417.     LPWSTR pwszTemp = new WCHAR[iLenData+1];
  418.     int iLenTemp;
  419.         
  420.     // Trim left:
  421.     while (pwszData[iscan] != NULL && (pwszData[iscan] == ' ' || pwszData[iscan] == '\t' ))
  422.         iscan++;
  423.     
  424.     // We have now scanned PAST whitespace- so copy the string:
  425.     wcscpy(pwszTemp,&pwszData[iscan]);
  426.     
  427.     // Now we need to do the TrimRight
  428.     iLenTemp = wcslen(pwszTemp);
  429.     
  430.     for (iscan = iLenTemp-1; iscan; iscan--)
  431.     {
  432.         if (!(pwszTemp[iscan] == ' ' || pwszTemp[iscan] == '\t' ) )
  433.             break;
  434.     }
  435.     pwszTemp[iscan+1] =NULL;
  436.     wcscpy(pwszData,pwszTemp);            
  437. }
  438.  
  439. ////////////////////////////////////////////////////////////////////////////////////////////////////
  440. /*  RemoveSpecialChars()   - Removes Tabs from passed string
  441.     
  442.     Parameters
  443.  
  444.     LPWSTR pwszLine         - Target String   
  445. */
  446. void RemoveSpecialChars(LPWSTR pwszLine)
  447. {
  448.     int iLen = wcslen(pwszLine);
  449.     for (int x = 0; x < iLen; x++)
  450.     {
  451.         switch (pwszLine[x])
  452.         {
  453.             case '\t':
  454.                 pwszLine[x] = ' '; // convert tabs to spaces..
  455.         }
  456.     }
  457. }
  458.  
  459. ////////////////////////////////////////////////////////////////////////////////////////////////////
  460. /*  ReadDataFromLine()   - Reads the Attribute and the Value from a passed line of text
  461.     
  462.     Parameters
  463.  
  464.         LPWSTR pwszLine         - Line to read
  465.         BSTR * pbsAttrib        - Attribute NAME to return
  466.         BSTR * pbsValue         - Value of the attribute
  467. */
  468. HRESULT ReadDataFromLine(LPWSTR pwszLine,BSTR * pbsAttrib, BSTR * pbsValue)
  469. {
  470.     int x;
  471.     int iLen = wcslen(pwszLine);    
  472.  
  473.     *pbsAttrib = NULL;
  474.     *pbsValue  = NULL;
  475.  
  476.     // Remove any tabs still in the line:
  477.     RemoveSpecialChars(pwszLine);
  478.     
  479.     // If this line is a comment or blank, bail..
  480.     if (pwszLine[0] == L'/' || iLen == 0)
  481.         return S_FALSE;
  482.         
  483.     // Make a temp string to save our string 
  484.     LPWSTR pwszTempAttrib = new WCHAR [iLen +1];
  485.     pwszTempAttrib[0]= NULL;
  486.  
  487.     for (x = 0; x< iLen; x++)
  488.         switch(pwszLine[x])
  489.         {
  490.              case L' ':
  491.              case L'\t':
  492.              {
  493.                 // NULL terminate the copy we are building
  494.                 pwszTempAttrib[x] = L'\0';
  495.                 x++;
  496.                 goto DoneReadDataFromLine;  
  497.                 break;
  498.              }
  499.              case NULL:    // if we hit the end of the string- there is NOT a value there
  500.              {
  501.                 wprintf(L"\n!!!Attribute missing value [%s]\n",pwszLine);
  502.                 return E_FAIL;
  503.              }
  504.              default:
  505.              {
  506.                 pwszTempAttrib[x] = pwszLine[x];   
  507.              }
  508.         }
  509.  
  510. DoneReadDataFromLine:
  511.     // Trim off any preceding spaces..
  512.     Trim((LPWSTR)pwszLine +x);
  513.  
  514.     // Grab the END of the passed line, and put it in the 
  515.     // Value BSTR
  516.     *pbsValue = SysAllocString((LPWSTR)pwszLine +x);
  517.     
  518.     // Alloc a new BSTR to return for this attribute
  519.     *pbsAttrib= SysAllocString(pwszTempAttrib);
  520.  
  521.     if (iLen)
  522.         delete [] pwszTempAttrib ;   
  523.     return S_OK;         
  524. }
  525.  
  526. ////////////////////////////////////////////////////////////////////////////////////////////////////
  527. /*  MakeOctetADSVALUE()   - Reads the passed octet string into the passed ADSVALUE,
  528.                             Sample String:
  529.                                     x00 x00 x00 x00 xe0 xff x03 xe0 xff x03 xe0 xff x03 xe0 xff x03 xe0 xff x03 x00 x00
  530.                             The "x"'s are required and the values must be in HEX format
  531.     
  532.     Parameters
  533.  
  534.     ADSVALUE *  pAdsValue    - Returned ADSVALUE of Type OctetString
  535.     LPWSTR      pwszOctet    - String representing OCTET
  536.  
  537. */
  538. HRESULT MakeOctetADSVALUE(ADSVALUE * pAdsValue,LPWSTR pwszOctet)
  539. {
  540.     int iNumBytes = 0;
  541.     int iStrLen = wcslen(pwszOctet);
  542.     
  543.     // Count the number of BYTES in the String
  544.     for (int x =0;x <iStrLen;x++)
  545.         if (pwszOctet[x] == L'x' || pwszOctet[x] == L'X')
  546.             iNumBytes ++;
  547.  
  548.     if (iNumBytes)
  549.     {
  550.         int iCurrByte =0;
  551.  
  552.         // Allocate the bytes
  553.         pAdsValue->OctetString.lpValue = new BYTE [iNumBytes+1];
  554.         pAdsValue->OctetString.dwLength = iNumBytes;
  555.  
  556.         for (int x =0;x <iStrLen;x++)
  557.             if (pwszOctet[x] == L'x' || pwszOctet[x] == L'X')
  558.             {
  559.                 x++;
  560.                 int iVal;
  561.                 // found an x so grab the data
  562.                 swscanf(  &pwszOctet[x], L"%x",&iVal);
  563.                 pAdsValue->OctetString.lpValue[iCurrByte++]= iVal;                      
  564.             
  565.                 // scan past the rest of the string
  566.                 for (x =x;x<iStrLen && pwszOctet[x] != (WCHAR)' ' ;x++)
  567.                     ;
  568.             }
  569.     }
  570.     else 
  571.         return E_FAIL;
  572.     
  573.     return S_OK;             
  574. }
  575.  
  576. ////////////////////////////////////////////////////////////////////////////////////////////////////
  577. /*  PopulateADSAttrInfo()   - Populates the passed ADS_ATTR_INFO from the passed attribute and Value
  578.     
  579.     Parameters
  580.  
  581.     ADS_ATTR_INFO * pattrInfo   - Pointer to Element to be added
  582.     LPWSTR pwszAttrib           - Name of the Attribute
  583.     LPWSTR pwszValue            - Value of the Attribute
  584.  
  585. */
  586. BOOL PopulateADSAttrInfo(ADS_ATTR_INFO * pattrInfo,LPWSTR pwszAttrib,LPWSTR pwszValue)
  587. {
  588.     // Look up the attribute name and get the TYPE string for this attribute
  589.     LPWSTR pwszType;
  590.     LPWSTR  pwszSingleMulti;
  591.     BOOL bAttribIsSingle = TRUE;
  592.  
  593.     BOOL bret;
  594.     
  595.     bret = MapUserAttribToType(pwszAttrib,&pwszType,&pwszSingleMulti);
  596.     if (!bret)
  597.     {
  598.         wprintf(L"\n!!!Error: unable to map %s\n",pwszAttrib);
  599.         return FALSE;
  600.     }
  601.  
  602.     if (_wcsicmp(pwszSingleMulti,L"MV")==0)
  603.         bAttribIsSingle = FALSE;
  604.     else
  605.         bAttribIsSingle = TRUE;        
  606.  
  607.     // Look up the string and get the corrosponding ADSVALUE...
  608.     ADSTYPE adType = MapTypeToADSTYPE(pwszType);
  609.  
  610.     if (adType == ADSTYPE_UNKNOWN)
  611.     {
  612.         wprintf(L"\n!!!Error: unable to map %s ADS_TYPE unknown\n",pwszAttrib);
  613.         return FALSE;
  614.     }
  615.     // FIll in the Attribute Name
  616.     pattrInfo->pszAttrName = new WCHAR [wcslen(pwszAttrib)+1];
  617.     wcscpy(pattrInfo->pszAttrName,pwszAttrib);
  618.     pattrInfo->dwControlCode  = ADS_ATTR_UPDATE;
  619.     pattrInfo->dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  620.  
  621.     pattrInfo->pADsValues = new ADSVALUE;
  622.     pattrInfo->pADsValues->dwType = adType;
  623.     pattrInfo->dwNumValues = 1;
  624.     
  625.     // Fill in the VALUE:
  626.     switch (adType )
  627.     {
  628.  
  629.         case ADSTYPE_DN_STRING:                
  630.         case ADSTYPE_CASE_EXACT_STRING:        
  631.         case ADSTYPE_CASE_IGNORE_STRING:        
  632.         case ADSTYPE_PRINTABLE_STRING:        
  633.         case ADSTYPE_NUMERIC_STRING:            
  634.         case ADSTYPE_TYPEDNAME:                
  635.         case ADSTYPE_FAXNUMBER:                
  636.         case ADSTYPE_PATH:                    
  637.         case ADSTYPE_OBJECT_CLASS:
  638.         {
  639.             pattrInfo->pADsValues->CaseIgnoreString = new WCHAR [wcslen(pwszValue)+1];
  640.             wcscpy(pattrInfo->pADsValues->CaseIgnoreString,pwszValue);
  641.  
  642.             break;
  643.         }
  644.         case ADSTYPE_BOOLEAN:
  645.             if (_wcsicmp(pwszValue,L"TRUE")==0)
  646.                 pattrInfo->pADsValues->Boolean = 1;
  647.             else if (_wcsicmp(pwszValue,L"FALSE")==0)
  648.                 pattrInfo->pADsValues->Boolean = 0;
  649.             else if (_wtoi(pwszValue)>0)
  650.                 pattrInfo->pADsValues->Boolean = 1;
  651.             else
  652.                 pattrInfo->pADsValues->Boolean = 0;
  653.             break;
  654.         case ADSTYPE_INTEGER:
  655.         {
  656.             pattrInfo->pADsValues->Integer = _wtoi(pwszValue);
  657.             break;
  658.         }
  659.         case ADSTYPE_OCTET_STRING:            
  660.         {
  661.             // Read the string into an actualy binary blob
  662.             HRESULT hr = MakeOctetADSVALUE(pattrInfo->pADsValues ,pwszValue);    
  663.             if (FAILED(hr))
  664.                 return FALSE;                    
  665.             break;
  666.         }                                                                        
  667.         case ADSTYPE_UTC_TIME:                
  668.         {
  669.             SYSTEMTIME pst;
  670.             
  671.             HRESULT hr = ConvertUTCFromStringToUTCTime( pwszValue,&pst );
  672.             
  673.             if (FAILED(hr))
  674.                 return FALSE;                    
  675.  
  676.             pattrInfo->pADsValues->UTCTime = pst;
  677.  
  678.             break;
  679.         }
  680.         case ADSTYPE_LARGE_INTEGER:            
  681.         {
  682.             pattrInfo->pADsValues->dwType = ADSTYPE_LARGE_INTEGER;
  683.             swscanf (pwszValue, L"%I64d", &pattrInfo->pADsValues->LargeInteger);
  684.             break;
  685.         }
  686.  
  687.         default:
  688.         {
  689.             wprintf(L"\n\n!!!ERROR Unrecognized Type for atrib: %s",pwszAttrib);
  690.             return FALSE;
  691.         }
  692.     }
  693.     return TRUE;
  694. }
  695.  
  696.  
  697. ////////////////////////////////////////////////////////////////////////////////////////////////////
  698. /*  PopulateAttrInfoFromFile()   - Populates the passed ADS_ATTR_INFO from the passed filename
  699.     
  700.     Parameters
  701.  
  702.     LPWSTR pwszFileName         - file from which info is read
  703.     ADS_ATTR_INFO * pattrInfo   - Pointer to Elements to be added
  704.     DWORD &rdwNumPopulated      - Returned number populated
  705. */
  706.  
  707. BOOL PopulateAttrInfoFromFile(LPWSTR pwszFileName,ADS_ATTR_INFO * pattrInfo,DWORD &rdwNumPopulated )
  708. {
  709.     HRESULT hr = S_OK;
  710.     BOOL    bRet = FALSE;
  711.     FILE * fpInput = NULL;
  712.     WCHAR  pwszLine[4096];
  713.     rdwNumPopulated = 0;
  714.  
  715.     if( (fpInput = _wfopen( pwszFileName, L"r" )) == NULL )
  716.     {
  717.         wprintf(L"\nError Opening Input File:%s",pwszFileName);
  718.         return FALSE;
  719.     }
  720.  
  721.     while (GetNextLine(fpInput,pwszLine,4096) && SUCCEEDED(hr))
  722.     {
  723.         Trim(pwszLine);
  724.         
  725.         BSTR bsAttrib;
  726.         BSTR bsValue;
  727.  
  728.         // Read the line into our BSTRS
  729.         // if S_FALSE is returned, then we do not have a line
  730.         // if E_FAIL is returned, then we have an error condition
  731.         hr = ReadDataFromLine(pwszLine,&bsAttrib,&bsValue);
  732.  
  733.         if (hr == S_OK) 
  734.         {
  735.             wprintf(L" attrib:%s value:%s\n",bsAttrib,bsValue);
  736.             
  737.             // Take the attribute and value and add them to the Array
  738.             if (!PopulateADSAttrInfo(&pattrInfo[rdwNumPopulated],bsAttrib,bsValue))
  739.             {
  740.                 hr = E_FAIL;
  741.                 break;
  742.             }
  743.  
  744.             SysFreeString(bsAttrib);
  745.             SysFreeString(bsValue);
  746.  
  747.             rdwNumPopulated++;
  748.         }
  749.     }
  750.     fclose(fpInput);
  751.     return (SUCCEEDED(hr));
  752. }
  753.  
  754.  
  755.  
  756.  
  757. ////////////////////////////////////////////////////////////////////////////////////////////////////
  758. /*  CreateUserFromFile()   - Function for creating a basic User
  759.     
  760.     Parameters
  761.  
  762.         IDirectoryObject *pDirObject    -   Parent Directory Object for the new User
  763.         LPWSTR pwCommonName             -   Common Name for the new User
  764.         IDirectoryObject ** ppDirObjRet -   Pointer to the Pointer which will receive the new User
  765.         int iUserType                  -   Bitflags for new User:
  766.                                                                     ADS_User_TYPE_GLOBAL_User, 
  767.                                                                     ADS_User_TYPE_DOMAIN_LOCAL_User, 
  768.                                                                     ADS_User_TYPE_UNIVERSAL_User, 
  769.                                                                     ADS_User_TYPE_SECURITY_ENABLED 
  770. */
  771. HRESULT CreateUserFromFile(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IDirectoryObject ** ppDirObjRet,LPWSTR pwszFileName)
  772. {
  773.     // To simply things, allocate a fixed array:
  774.     ADS_ATTR_INFO   attrInfo [MAX_ATTRIBS+1];
  775.  
  776.     HRESULT         hr = S_OK;
  777.     DWORD           dwNumPopulated;
  778.     LPDISPATCH      pDisp;
  779.     *ppDirObjRet     = NULL;
  780.     WCHAR           pwCommonNameFull[MAX_PATH*2];
  781.     BOOL    bRet = FALSE;
  782.     FILE * fpInput = NULL;
  783.     WCHAR  pwszLine[4096];
  784.     dwNumPopulated = 0;
  785.  
  786.     if( (fpInput = _wfopen( pwszFileName, L"r" )) == NULL )
  787.     {
  788.         wprintf(L"\nError Opening Input File:%s",pwszFileName);
  789.         return FALSE;
  790.     }
  791.  
  792.     while (GetNextLine(fpInput,pwszLine,4096) && SUCCEEDED(hr))
  793.     {
  794.         Trim(pwszLine);
  795.         
  796.         BSTR bsAttrib;
  797.         BSTR bsValue;
  798.  
  799.         // Read the line into our BSTRS
  800.         // if S_FALSE is returned, then we do not have a line
  801.         // if E_FAIL is returned, then we have an error condition
  802.         hr = ReadDataFromLine(pwszLine,&bsAttrib,&bsValue);
  803.  
  804.         if (hr == S_OK) 
  805.         {
  806.             wprintf(L" attrib:%s value:%s\n",bsAttrib,bsValue);
  807.             
  808.             // Take the attribute and value and add them to the Array
  809.             if (!PopulateADSAttrInfo(&attrInfo[dwNumPopulated],bsAttrib,bsValue))
  810.             {
  811.                 hr = E_FAIL;
  812.                 break;
  813.             }
  814.  
  815.             SysFreeString(bsAttrib);
  816.             SysFreeString(bsValue);
  817.             dwNumPopulated++;
  818.         }
  819.     }
  820.     fclose(fpInput);
  821.  
  822.     wsprintfW(pwCommonNameFull,L"CN=%s",pwCommonName);
  823.  
  824.     hr = pDirObject->CreateDSObject( pwCommonNameFull,  attrInfo, 
  825.     dwNumPopulated, &pDisp );
  826.  
  827.     if (SUCCEEDED(hr))
  828.     {
  829.         hr = pDisp->QueryInterface(IID_IDirectoryObject,(void**) ppDirObjRet);
  830.  
  831.         pDisp->Release();
  832.         pDisp = NULL;
  833.     }
  834.  
  835.     //FreeAttrInfo(attrInfo);
  836.  
  837.     return hr;
  838. }
  839.  
  840. ////////////////////////////////////////////////////////////////////////////////////////////////////
  841. /*  CreateUser()   - Function for creating a basic User
  842.     
  843.     Parameters
  844.  
  845.         IDirectoryObject *pDirObject    -   Parent Directory Object for the new User
  846.         LPWSTR pwCommonName             -   Common Name for the new User
  847.         IDirectoryObject ** ppDirObjRet -   Pointer to the Pointer which will receive the new User
  848.         int iUserType                  -   Bitflags for new User:
  849.                                                                     ADS_User_TYPE_GLOBAL_User, 
  850.                                                                     ADS_User_TYPE_DOMAIN_LOCAL_User, 
  851.                                                                     ADS_User_TYPE_UNIVERSAL_User, 
  852.                                                                     ADS_User_TYPE_SECURITY_ENABLED 
  853. */
  854. HRESULT CreateUser(IDirectoryObject *pDirObject, LPWSTR pwCommonName,LPWSTR pwSamAcctName,IDirectoryObject ** ppDirObjRet)
  855. {
  856.     assert(pDirObject);
  857.     if (wcslen(pwSamAcctName) >20)
  858.     {
  859.         MessageBox(NULL,L"SamAccountName CANNOT be bigger than 20 characters",L"Error: CreateSimpleUser()",MB_ICONSTOP);
  860.         assert(0);
  861.         return E_FAIL;
  862.     }
  863.  
  864.     HRESULT    hr;
  865.     ADSVALUE   sAMValue;
  866.     ADSVALUE   classValue;
  867.     LPDISPATCH pDisp;
  868.     WCHAR       pwCommonNameFull[1024];
  869.     
  870.     ADS_ATTR_INFO  attrInfo[] = 
  871.     {  
  872.        { L"objectClass", ADS_ATTR_UPDATE, 
  873.                            ADSTYPE_CASE_IGNORE_STRING, &classValue, 1 },
  874.        {L"sAMAccountName", ADS_ATTR_UPDATE, 
  875.                            ADSTYPE_CASE_IGNORE_STRING, &sAMValue, 1},
  876.     };
  877.  
  878.     DWORD dwAttrs = sizeof(attrInfo)/sizeof(ADS_ATTR_INFO); 
  879.     classValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
  880.     classValue.CaseIgnoreString = L"User";
  881.    
  882.     sAMValue.dwType=ADSTYPE_CASE_IGNORE_STRING;
  883.     sAMValue.CaseIgnoreString = pwSamAcctName;
  884.  
  885.     wsprintfW(pwCommonNameFull,L"CN=%s",pwCommonName);
  886.      
  887.     hr = pDirObject->CreateDSObject( pwCommonNameFull,  attrInfo, 
  888.                                 dwAttrs, &pDisp );
  889.     if (SUCCEEDED(hr))
  890.     {
  891.         hr = pDisp->QueryInterface(IID_IDirectoryObject,(void**) ppDirObjRet);
  892.  
  893.         pDisp->Release();
  894.         pDisp = NULL;
  895.     }
  896.     return hr;
  897. }
  898.  
  899.  
  900.