#include "headers.hxx" #pragma hdrstop #include #include // // Helpful debug macros // #define DBG_OUT_HRESULT(hr) printf("error 0x%x at line %u\n", hr, __LINE__) #define BREAK_ON_FAIL_HRESULT(hr) \ if (FAILED(hr)) \ { \ DBG_OUT_HRESULT(hr); \ break; \ } // // Forward references // VOID DumpDsSelectedItemList( PDSSELECTIONLIST pDsSelList, ULONG cRequestedAttributes, LPCTSTR *aptzRequestedAttributes); VOID Usage(); HRESULT AnsiToUnicode( LPWSTR pwszTo, LPCSTR szFrom, LONG cchTo); BOOL ParseFetchSwitch( char *pzFetchSwitch, PULONG pcRequestedAttributes, LPCTSTR **paptzRequestedAttributes); BOOL ParseGroupSwitch( char *pzGroupSwitch, ULONG *pulFlags); BOOL ParseUserSwitch( char *pzUserSwitch, ULONG *pulFlags); BOOL ParseInitialScope( char *pzScopeSwitch, ULONG *pulFlags); BOOL ParseScope( char *pzScopeSwitch, ULONG *pulFlags, PWSTR wzComputer, PWSTR wzDomain); BOOL ParseProviders( char *pzProviderSwitch, PULONG cAcceptableProviders, LPCWSTR **paptzAcceptableProviders); BOOL ParseRunCount( char *pzRunCountSwitch, PULONG pcRunCount); LPWSTR VariantString( VARIANT *pvar); void VarArrayToStr( VARIANT *pvar, LPWSTR wzBuf, ULONG cchbuf); // // Entry point // enum API_TO_CALL { NONE, COMPUTER, USER_GROUP }; void _cdecl main(int argc, char * argv[]) { HRESULT hr; BOOL fBadArg = FALSE; API_TO_CALL api = NONE; ULONG flObjectPicker = 0; ULONG flDsObjectPicker = 0; ULONG flUserGroupObjectPickerSpecifiedDomain = 0; ULONG flUserGroupObjectPickerOtherDomains = 0; ULONG *pflUserGroup = &flUserGroupObjectPickerOtherDomains; ULONG flComputerObjectPicker = 0; ULONG flInitialScope = 0; WCHAR wzComputer[MAX_PATH] = L""; WCHAR wzDomain[MAX_PATH] = L""; ULONG cAcceptableProviders = 0; LPCWSTR *aptzAcceptableProviders = NULL; ULONG cInvocations = 1; ULONG cRequestedAttributes = 0; LPCTSTR *aptzRequestedAttributes = NULL; for (int idxArg = 1; idxArg < argc && !fBadArg; idxArg++) { switch (argv[idxArg][1]) { case 'c': case 'C': if (argv[idxArg][2] == ':' && tolower(argv[idxArg][3]) == 'a') { if (api == USER_GROUP) { fBadArg = TRUE; printf("Can't specify /C:Api with user/group switches\n"); } api = COMPUTER; } else { if (api == COMPUTER) { fBadArg = TRUE; printf("Can't specify both /C and /C:Api\n"); } api = USER_GROUP; *pflUserGroup |= UGOP_COMPUTERS; } break; case 'd': case 'D': if (argv[idxArg][2] != ':') { printf("Expected ':' after /D\n"); fBadArg = TRUE; break; } switch (argv[idxArg][3]) { case 's': case 'S': pflUserGroup = &flUserGroupObjectPickerSpecifiedDomain; break; case 'o': case 'O': case '0': // allow a typo pflUserGroup = &flUserGroupObjectPickerOtherDomains; break; default: fBadArg = TRUE; printf("Expected S or O after /D:\n"); break; } break; case 'f': case 'F': fBadArg = !ParseFetchSwitch(argv[idxArg], &cRequestedAttributes, &aptzRequestedAttributes); break; case 'g': case 'G': if (api != NONE && api != USER_GROUP) { fBadArg = TRUE; break; } api = USER_GROUP; fBadArg = !ParseGroupSwitch(argv[idxArg], pflUserGroup); break; case 'h': case 'H': if (api != NONE && api != USER_GROUP) { fBadArg = TRUE; break; } api = USER_GROUP; *pflUserGroup |= UGOP_INCLUDE_HIDDEN; break; case 'i': case 'I': fBadArg = !ParseInitialScope(argv[idxArg], &flInitialScope); break; case 'm': case 'M': flObjectPicker |= OP_MULTISELECT; break; case 'n': case 'N': flDsObjectPicker |= DSOP_RESTRICT_NAMES_TO_KNOWN_DOMAINS; break; case 'p': case 'P': fBadArg = !ParseProviders(argv[idxArg], &cAcceptableProviders, &aptzAcceptableProviders); break; case 'r': case 'R': fBadArg = !ParseRunCount(argv[idxArg], &cInvocations); break; case 's': case 'S': fBadArg = !ParseScope(argv[idxArg], &flDsObjectPicker, wzComputer, wzDomain); break; case 'u': case 'U': if (api == COMPUTER) { fBadArg = TRUE; break; } api = USER_GROUP; fBadArg = !ParseUserSwitch(argv[idxArg], pflUserGroup); break; case 'x': case 'X': flDsObjectPicker |= DSOP_CONVERT_EXTERNAL_PATHS_TO_SID; break; default: fBadArg = TRUE; break; } } if (fBadArg || api == NONE) { Usage(); return; } hr = CoInitialize(NULL); if (FAILED(hr)) { printf("CoInitializeEx - 0x%x\n", hr); return; } // // Call the API // PDSSELECTIONLIST pDsSelList = NULL; if (api == USER_GROUP) { GETUSERGROUPSELECTIONINFO ugsi; ZeroMemory(&ugsi, sizeof ugsi); ugsi.cbSize = sizeof(ugsi); ugsi.ptzComputerName = *wzComputer ? wzComputer : NULL; ugsi.ptzDomainName = *wzDomain ? wzDomain : NULL; ugsi.flObjectPicker = flObjectPicker; ugsi.flDsObjectPicker = flDsObjectPicker; ugsi.flStartingScope = flInitialScope; ugsi.flUserGroupObjectPickerSpecifiedDomain = flUserGroupObjectPickerSpecifiedDomain; ugsi.flUserGroupObjectPickerOtherDomains = flUserGroupObjectPickerOtherDomains; ugsi.ppDsSelList = &pDsSelList; ugsi.cAcceptableProviders = cAcceptableProviders; ugsi.aptzAcceptableProviders = aptzAcceptableProviders; ugsi.cRequestedAttributes = cRequestedAttributes; ugsi.aptzRequestedAttributes = aptzRequestedAttributes; for (ULONG i = 0; i < cInvocations; i++) { hr = GetUserGroupSelection(&ugsi); if (hr == S_FALSE) { printf("Invocation %u: User/Group picker dialog cancelled\n", i); } else if (SUCCEEDED(hr)) { DumpDsSelectedItemList(pDsSelList, cRequestedAttributes, aptzRequestedAttributes); } else { printf("Invocation %u: User/Group picker dialog failed 0x%x\n", i, hr); } FreeDsSelectionList(pDsSelList); pDsSelList = NULL; } } else if (api == COMPUTER) { GETCOMPUTERSELECTIONINFO csi; ZeroMemory(&csi, sizeof csi); csi.cbSize = sizeof(csi); csi.ptzComputerName = *wzComputer ? wzComputer : NULL; csi.ptzDomainName = *wzDomain ? wzDomain : NULL; csi.flObjectPicker = flObjectPicker; csi.flDsObjectPicker = flDsObjectPicker; csi.flStartingScope = flInitialScope; csi.flComputerObjectPicker = flComputerObjectPicker; csi.ppDsSelList = &pDsSelList; csi.cAcceptableProviders = cAcceptableProviders; csi.aptzAcceptableProviders = aptzAcceptableProviders; csi.cRequestedAttributes = cRequestedAttributes; csi.aptzRequestedAttributes = aptzRequestedAttributes; for (ULONG i = 0; i < cInvocations; i++) { hr = GetComputerSelection(&csi); if (hr == S_FALSE) { printf("Invocation %u: Computer picker dialog cancelled\n", i); } else if (SUCCEEDED(hr)) { DumpDsSelectedItemList(pDsSelList, cRequestedAttributes, aptzRequestedAttributes); } else { printf("Invocation %u: Computer picker dialog failed 0x%x\n", i, hr); } FreeDsSelectionList(pDsSelList); pDsSelList = NULL; } } else { printf("unexpected api setting\n"); } CoUninitialize(); } LPWSTR apwzAttr[100]; BOOL ParseFetchSwitch( char *pzFetchSwitch, PULONG pcRequestedAttributes, LPCTSTR **paptzRequestedAttributes) { BOOL fOk = TRUE; pzFetchSwitch += 2; // advance past '/' (or '-') and 'G' if (*pzFetchSwitch != ':') { printf("expected : after /Fetch\n"); return FALSE; } *pcRequestedAttributes = 0; *paptzRequestedAttributes = NULL; ULONG cRequestedAttributes = 0; for (pzFetchSwitch++; *pzFetchSwitch && fOk; pzFetchSwitch++) { if (*pzFetchSwitch == ',') { continue; } PSTR pzComma = strchr(pzFetchSwitch, ','); if (pzComma) { *pzComma = '\0'; } ULONG cchFetchSwitch = strlen(pzFetchSwitch) + 1; // BUGBUG this is leaked. (who cares?) apwzAttr[cRequestedAttributes] = new WCHAR[cchFetchSwitch]; if (!apwzAttr[cRequestedAttributes]) { printf("out of memory\n"); return FALSE; } AnsiToUnicode(apwzAttr[cRequestedAttributes], pzFetchSwitch, cchFetchSwitch); cRequestedAttributes++; if (pzComma) { *pzComma = ','; pzFetchSwitch = pzComma; } else { pzFetchSwitch += strlen(pzFetchSwitch) - 1; } } if (cRequestedAttributes && fOk) { *pcRequestedAttributes = cRequestedAttributes; *paptzRequestedAttributes = (LPCTSTR *)apwzAttr; } return fOk; } BOOL ParseGroupSwitch( char *pzGroupSwitch, ULONG *pulFlags) { BOOL fOk = TRUE; pzGroupSwitch += 2; // advance past '/' (or '-') and 'G' if (*pzGroupSwitch != ':') { printf("expected : after /Groups\n"); return FALSE; } for (pzGroupSwitch++; *pzGroupSwitch && fOk; pzGroupSwitch++) { if (*pzGroupSwitch == ',') { continue; } PSTR pzComma = strchr(pzGroupSwitch, ','); if (pzComma) { *pzComma = '\0'; } BOOL fMatch = FALSE; if (!lstrcmpiA(pzGroupSwitch, "all")) { fMatch = TRUE; *pulFlags |= UGOP_ALL_GROUPS; } if (pzComma) { *pzComma = ','; } if (fMatch) { if (pzComma) { pzGroupSwitch = pzComma; } else { pzGroupSwitch += strlen(pzGroupSwitch) - 1; } continue; } switch (tolower(*pzGroupSwitch)) { case 'u': if (tolower(pzGroupSwitch[1]) == 's') { *pulFlags |= UGOP_UNIVERSAL_GROUPS_SE; pzGroupSwitch++; } else { *pulFlags |= UGOP_UNIVERSAL_GROUPS; } break; case 'a': if (tolower(pzGroupSwitch[1]) == 's') { *pulFlags |= UGOP_ACCOUNT_GROUPS_SE; pzGroupSwitch++; } else { *pulFlags |= UGOP_ACCOUNT_GROUPS; } break; case 'r': if (tolower(pzGroupSwitch[1]) == 's') { *pulFlags |= UGOP_RESOURCE_GROUPS_SE; pzGroupSwitch++; } else { *pulFlags |= UGOP_RESOURCE_GROUPS; } break; case 'l': *pulFlags |= UGOP_LOCAL_GROUPS; break; case 'g': *pulFlags |= UGOP_GLOBAL_GROUPS; break; case 'b': *pulFlags |= UGOP_BUILTIN_GROUPS; break; case 'w': *pulFlags |= UGOP_WELL_KNOWN_PRINCIPALS_USERS; break; default: fOk = FALSE; printf("unexpected character '%c' in group type switch\n", *pzGroupSwitch); break; } } printf("flags = 0x%x\n", *pulFlags); return fOk; } BOOL ParseUserSwitch( char *pzUserSwitch, ULONG *pulFlags) { BOOL fOk = TRUE; pzUserSwitch += 2; // advance past '/' (or '-') and 'U' if (*pzUserSwitch != ':') { printf("expected : after /Users\n"); return FALSE; } for (pzUserSwitch++; *pzUserSwitch && fOk; pzUserSwitch++) { if (*pzUserSwitch == ',') { continue; } PSTR pzComma = strchr(pzUserSwitch, ','); if (pzComma) { *pzComma = '\0'; } BOOL fMatch = FALSE; if (!lstrcmpiA(pzUserSwitch, "all")) { fMatch = TRUE; *pulFlags |= UGOP_ALL_USERS; } else if (!lstrcmpiA(pzUserSwitch, "world")) { fMatch = TRUE; *pulFlags |= UGOP_USER_WORLD; } else if (!lstrcmpiA(pzUserSwitch, "authenticated")) { fMatch = TRUE; *pulFlags |= UGOP_USER_AUTHENTICATED_USER; } else if (!lstrcmpiA(pzUserSwitch, "anonymous")) { fMatch = TRUE; *pulFlags |= UGOP_USER_ANONYMOUS; } else if (!lstrcmpiA(pzUserSwitch, "dialup")) { fMatch = TRUE; *pulFlags |= UGOP_USER_DIALUP; } else if (!lstrcmpiA(pzUserSwitch, "network")) { fMatch = TRUE; *pulFlags |= UGOP_USER_NETWORK; } else if (!lstrcmpiA(pzUserSwitch, "Batch")) { fMatch = TRUE; *pulFlags |= UGOP_USER_BATCH; } else if (!lstrcmpiA(pzUserSwitch, "Interactive")) { fMatch = TRUE; *pulFlags |= UGOP_USER_INTERACTIVE; } else if (!lstrcmpiA(pzUserSwitch, "Service")) { fMatch = TRUE; *pulFlags |= UGOP_USER_SERVICE; } else if (!lstrcmpiA(pzUserSwitch, "System")) { fMatch = TRUE; *pulFlags |= UGOP_USER_SYSTEM; } if (pzComma) { *pzComma = ','; } if (fMatch) { if (pzComma) { pzUserSwitch = pzComma; } else { pzUserSwitch += strlen(pzUserSwitch) - 1; } continue; } switch (tolower(*pzUserSwitch)) { case 'u': *pulFlags |= UGOP_USERS; break; case 'c': *pulFlags |= UGOP_CONTACTS; break; default: fOk = FALSE; printf("unexpected character '%c' in user type switch\n", *pzUserSwitch); break; } if (pzComma) { pzUserSwitch = pzComma; } } return fOk; } BOOL ParseInitialScope( char *pzScopeSwitch, ULONG *pulFlags) { PSTR pzCur = strchr(pzScopeSwitch, ':'); if (!pzCur) { printf("expected : after /InitialScope switch\n"); return FALSE; } // advance past colon pzCur++; switch (tolower(*pzCur)) { case 'c': *pulFlags |= DSOP_SCOPE_SPECIFIED_MACHINE; break; case 'd': *pulFlags |= DSOP_SCOPE_SPECIFIED_DOMAIN; break; case 'g': *pulFlags |= DSOP_SCOPE_DIRECTORY; break; case 't': *pulFlags |= DSOP_SCOPE_DOMAIN_TREE; break; case 'x': *pulFlags |= DSOP_SCOPE_EXTERNAL_TRUSTED_DOMAINS; break; default: printf("invalid /InitialScope switch\n"); return FALSE; } return TRUE; } BOOL ParseProviders( char *pzProviderSwitch, PULONG pcAcceptableProviders, LPCWSTR **paptzAcceptableProviders) { BOOL fOk = TRUE; PSTR pzCur = strchr(pzProviderSwitch, ':'); static LPCWSTR apwzProviders[3]; *paptzAcceptableProviders = apwzProviders; if (!pzCur) { printf("expected : after /Providers switch\n"); return FALSE; } ZeroMemory(apwzProviders, sizeof apwzProviders); // advance past colon pzCur++; while (*pzCur) { switch (tolower(*pzCur)) { case 'w': apwzProviders[(*pcAcceptableProviders)++] = L"WinNT"; break; case 'l': apwzProviders[(*pcAcceptableProviders)++] = L"LDAP"; break; case 'g': apwzProviders[(*pcAcceptableProviders)++] = L"GC"; break; default: printf("invalid provider switch\n"); return FALSE; } for (; *pzCur && *pzCur != ','; pzCur++) { } if (*pzCur == ',') { pzCur++; } // ignore extras if (*pcAcceptableProviders == 3) { break; } } return fOk; } BOOL ParseRunCount( char *pzRunCountSwitch, PULONG pcRunCount) { PSTR pzCur = strchr(pzRunCountSwitch, ':'); if (!pzCur) { printf("expected : after /Runcount switch\n"); return FALSE; } *pcRunCount = (ULONG) atol(pzCur + 1); if (!*pcRunCount || *pcRunCount > 10) { printf("Invalid run count %u\n", *pcRunCount); } return TRUE; } BOOL ParseScope( char *pzScopeSwitch, ULONG *pulFlags, PWSTR wzComputer, PWSTR wzDomain) { PSTR pzCur = strchr(pzScopeSwitch, ':'); if (!pzCur) { printf("expected : after /Scope switch\n"); return FALSE; } // advance past colon pzCur++; while (*pzCur) { switch (tolower(*pzCur)) { case 'c': { *pulFlags |= DSOP_SCOPE_SPECIFIED_MACHINE; // find '=' for (PSTR pzEqual = pzCur; *pzEqual && *pzEqual != ',' && *pzEqual != '='; pzEqual++) { } if (*pzEqual == '=') { CHAR szTemp[MAX_PATH]; strcpy(szTemp, pzEqual + 1); LPSTR pzComma = strchr(szTemp, ','); if (pzComma) { *pzComma = '\0'; } AnsiToUnicode(wzComputer, szTemp, MAX_PATH); pzCur = pzEqual + 1; } break; } case 'd': { *pulFlags |= DSOP_SCOPE_SPECIFIED_DOMAIN; for (PSTR pzEqual = pzCur; *pzEqual && *pzEqual != ',' && *pzEqual != '='; pzEqual++) { } if (*pzEqual == '=') { CHAR szTemp[MAX_PATH]; LPSTR pzOpenQuote = strchr(pzEqual, '\''); if (!pzOpenQuote) { printf("Expected single quote after = in domain spec\n"); return FALSE; } LPSTR pzCloseQuote = strchr(pzOpenQuote + 1, '\''); if (!pzCloseQuote) { printf("Expected closing single quote after = in domain spec\n"); return FALSE; } CopyMemory(szTemp, pzOpenQuote + 1, pzCloseQuote - pzOpenQuote - 1); szTemp[pzCloseQuote - pzOpenQuote - 1] = '\0'; AnsiToUnicode(wzDomain, szTemp, MAX_PATH); pzCur = pzCloseQuote + 1; } break; } case 'g': *pulFlags |= DSOP_SCOPE_DIRECTORY; break; case 't': *pulFlags |= DSOP_SCOPE_DOMAIN_TREE; break; case 'x': *pulFlags |= DSOP_SCOPE_EXTERNAL_TRUSTED_DOMAINS; break; default: printf("invalid scope switch\n"); return FALSE; } for (; *pzCur && *pzCur != ','; pzCur++) { } if (*pzCur == ',') { pzCur++; } } return TRUE; } //+-------------------------------------------------------------------------- // // Function: DumpDsSelectedItemList // // Synopsis: Dump the contents of the list of DS items the user selected // to the console. // // Arguments: [pDsSelList] - list of Ds items // // History: 11-04-1997 DavidMun Created // //--------------------------------------------------------------------------- VOID DumpDsSelectedItemList( PDSSELECTIONLIST pDsSelList, ULONG cRequestedAttributes, LPCTSTR *aptzRequestedAttributes) { if (!pDsSelList) { printf("List is empty\n"); return; } ULONG i; PDSSELECTION pCur = &pDsSelList->aDsSelection[0]; for (i = 0; i < pDsSelList->cItems; i++, pCur++) { printf("Name: %ws\n", pCur->pwzName); printf("Class: %ws\n", pCur->pwzClass); printf("Path: %ws\n", pCur->pwzADsPath); printf("UPN: %ws\n", pCur->pwzUPN); for (ULONG j = 0; j < cRequestedAttributes; j++) { printf("Attr %02u: %ws = %ws\n", j, aptzRequestedAttributes[j], VariantString(&pCur->pvarOtherAttributes[j])); } printf("\n"); } } LPWSTR VariantString( VARIANT *pvar) { static WCHAR wzBuf[1024]; wzBuf[0] = L'\0'; switch (pvar->vt) { case VT_EMPTY: lstrcpy(wzBuf, L"VT_EMPTY"); break; case VT_NULL: lstrcpy(wzBuf, L"VT_NULL"); break; case VT_I2: wsprintf(wzBuf, L"%d", V_I2(pvar)); break; case VT_I4: wsprintf(wzBuf, L"%d", V_I4(pvar)); break; case VT_R4: wsprintf(wzBuf, L"%f", V_R4(pvar)); break; case VT_R8: wsprintf(wzBuf, L"%f", V_R8(pvar)); break; case VT_CY: wsprintf(wzBuf, L"$%f", V_CY(pvar)); break; case VT_DATE: wsprintf(wzBuf, L"date %f", V_DATE(pvar)); break; case VT_BSTR: if (V_BSTR(pvar)) { wsprintf(wzBuf, L"'%ws'", V_BSTR(pvar)); } else { lstrcpy(wzBuf, L"VT_BSTR NULL"); } break; case VT_DISPATCH: wsprintf(wzBuf, L"VT_DISPATCH 0x%x", V_DISPATCH(pvar)); break; case VT_UNKNOWN: wsprintf(wzBuf, L"VT_UNKNOWN 0x%x", V_UNKNOWN(pvar)); break; case VT_ERROR: case VT_HRESULT: wsprintf(wzBuf, L"hr 0x%x", V_ERROR(pvar)); break; case VT_BOOL: wsprintf(wzBuf, L"%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break; case VT_VARIANT: wsprintf(wzBuf, L"variant 0x%x", V_VARIANTREF(pvar)); break; case VT_DECIMAL: lstrcpy(wzBuf, L"VT_DECIMAL"); break; case VT_I1: wsprintf(wzBuf, L"%d", V_I1(pvar)); break; case VT_UI1: wsprintf(wzBuf, L"%u", V_UI1(pvar)); break; case VT_UI2: wsprintf(wzBuf, L"%u", V_UI2(pvar)); break; case VT_UI4: wsprintf(wzBuf, L"%u", V_UI4(pvar)); break; case VT_I8: lstrcpy(wzBuf, L"VT_I8"); break; case VT_UI8: lstrcpy(wzBuf, L"VT_UI8"); break; case VT_INT: wsprintf(wzBuf, L"%d", V_INT(pvar)); break; case VT_UINT: wsprintf(wzBuf, L"%u", V_UINT(pvar)); break; case VT_VOID: lstrcpy(wzBuf, L"VT_VOID"); break; case VT_UI1 | VT_ARRAY: VarArrayToStr(pvar, wzBuf, ARRAYLEN(wzBuf)); break; case VT_PTR: case VT_SAFEARRAY: case VT_CARRAY: case VT_USERDEFINED: case VT_LPSTR: case VT_LPWSTR: case VT_RECORD: case VT_FILETIME: case VT_BLOB: case VT_STREAM: case VT_STORAGE: case VT_STREAMED_OBJECT: case VT_STORED_OBJECT: case VT_BLOB_OBJECT: case VT_CF: case VT_CLSID: case VT_BSTR_BLOB: default: wsprintf(wzBuf, L"VT 0x%x", V_VT(pvar)); break; } return wzBuf; } void VarArrayToStr( VARIANT *pvar, LPWSTR wzBuf, ULONG cchBuf) { ULONG i; LPWSTR pwzNext = wzBuf; LPWSTR pwzEnd = wzBuf + cchBuf; for (i = 0; i < pvar->parray->rgsabound[0].cElements && pwzNext < pwzEnd + 6; i++) { wsprintf(pwzNext, L"x%02x ", ((LPBYTE)(pvar->parray->pvData))[i]); pwzNext += lstrlen(pwzNext); } } VOID Usage() { printf("\n"); printf("Usage: opt \n"); printf("\n"); printf("Switches are:\n"); printf(" /Computers[:Api]\n"); printf(" If API is specified, GetComputerSelection is called, otherwise\n"); printf(" this means include computer objects in the query\n"); printf(" /Domain:{S|O}\n"); printf(" If S is specified, then any following /Users, /Groups, or\n"); printf(" /Computers switches apply only to the specified domain scope.\n"); printf(" Otherwise, those switches apply to all other scopes\n"); printf(" /Fetch:[,]...\n"); printf(" is the name of an attribute to retrieve\n"); printf(" /Groups:[,]...\n"); printf(" is one of:\n"); printf(" ALL - same as specifiying each of the following\n"); printf(" U - Universal\n"); printf(" A - Account\n"); printf(" R - Resource\n"); printf(" US - Universal Security Enabled\n"); printf(" AS - Account Security Enabled\n"); printf(" RS - Resource Security Enabled\n"); printf(" L - Local\n"); printf(" G - Global\n"); printf(" B - Builtin\n"); printf(" W - Well-Known Security Principals\n"); printf(" /Hidden\n"); printf(" Include objects hidden from address book.\n"); printf(" /Initialscope:{Computer|Domain|Gc|Tree|Xternal}\n"); printf(" /Multiselect\n"); printf(" /Namerestrict - reject names in unknown domains\n"); printf(" /Providers:[,]\n"); printf(" is one of:\n"); printf(" WINNT\n"); printf(" LDAP\n"); printf(" GC\n"); printf(" /Runcount:\n"); printf(" is number of times to invoke object picker\n"); printf(" /Scopes:[,]...\n"); printf(" is one of:\n"); printf(" Computer[=name]\n"); printf(" Domain[='']\n"); printf(" Gc\n"); printf(" Tree\n"); printf(" Xternal\n"); printf(" is one of:\n"); printf(" - the ADs path of a DS namespace\n"); printf(" - the flat name of a downlevel domain\n"); printf(" /Users:[,]...\n"); printf(" is one of:\n"); printf(" ALL - same as specifying each of the following\n"); printf(" U - User\n"); printf(" C - Contact\n"); printf(" WORLD\n"); printf(" AUTHENTICATED\n"); printf(" ANONYMOUS\n"); printf(" DIALUP\n"); printf(" NETWORK\n"); printf(" BATCH\n"); printf(" INTERACTIVE\n"); printf(" SERVICE\n"); printf(" SYSTEM\n"); printf(" /Xternal - force conversion of external paths to SIDs\n"); printf("\n"); printf("You must specify the Scope switch and at least one of the Computers,\n"); printf("Groups, or Users switches.\n"); printf("The significant characters in the switches are shown in upper case.\n"); } //+--------------------------------------------------------------------------- // // Function: AnsiToUnicode // // Synopsis: Convert ANSI string [szFrom] to Unicode string in buffer // [pwszTo]. // // Arguments: [pwszTo] - destination buffer // [szFrom] - source string // [cchTo] - size of destination buffer, in WCHARS // // Returns: S_OK - conversion succeeded // HRESULT_FROM_WIN32 - MultiByteToWideChar failed // // Modifies: *[pwszTo] // // History: 10-29-96 DavidMun Created // // Notes: The string in [pwszTo] will be NULL terminated even on // failure. // //---------------------------------------------------------------------------- HRESULT AnsiToUnicode( LPWSTR pwszTo, LPCSTR szFrom, LONG cchTo) { HRESULT hr = S_OK; ULONG cchWritten; cchWritten = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, pwszTo, cchTo); if (!cchWritten) { pwszTo[cchTo - 1] = L'\0'; // ensure NULL termination hr = HRESULT_FROM_WIN32(GetLastError()); printf("AnsiToUnicode: MultiByteToWideChar hr=0x%x\n", hr); } return hr; }